單頁應用 - Token 驗證

小綜哥發表於2017-03-28
第一次接觸單頁應用,記錄公司專案關於Token驗證知識.

Token的工作原理

單頁應用 - Token 驗證
Token工作原理

1. 登入時候,客戶端通過使用者名稱與密碼請求登入
2. 服務端收到請求區驗證使用者名稱與密碼
3. 驗證通過,服務端會簽發一個Token,再把這個Token發給客戶端.
4. 客戶端收到Token,儲存到本地,如Cookie,SessionStorage,LocalStorage.我們是存在SessionStorage
5. 客戶端每次像伺服器請求API介面時候,都要帶上Token.
6. 服務端收到請求,驗證Token,如果通過就返回資料,否則提示報錯資訊.複製程式碼

這裡還涉及到一些前端登入攔截(路由攔截,攔截器).

  • 路由攔截
// 登入路由設定個欄位,用來記錄是否已經登入
path: '/login', name:'login',
    component: resolve => require(['./login.vue'], resolve),
    meta: { noCheckSession: true }複製程式碼
// 路由攔截
router.beforeEach((to, from, next) => {
  if(to.matched.some(record => !record.meta.noCheckSession)) {
    let isLogin = auth.checkAuth() //我們登入成功後會設定個欄位(authenticated)為true.這裡就是獲取那個欄位.
    if(!isLogin){
      console.error('Place login!')
      next({
        path: '/login',
        query: { redirect: to.fullPath } // 跳轉到登入頁面
      })
    }else{
      next()
    }
  }else{
    next()
  }
  }複製程式碼
  • 攔截器
export const interceptor = function(Vue){
  Vue.http.interceptors.push((request, next)=>{
    let tokenVal = sessionStorage.getItem("token"); // 取出Tolen
    if(tokenVal) {
      request.headers['token'] = tokenVal  // 存在的話,把Token放在請求頭中
    }

    next((response)=>{
      let status = response.status
      let data = response.data
      try{
        if(typeof data === 'string'){
          data = JSON.parse(data)
        }
      }catch(e){

      }
      let isError = false
      let duration = 0
      let options = {
        message: ""
      }
      if(status === 401 ) {
        location.href = '/login'  // 401未授權,重新登入
      }else if (status === 500){
        isError = true
        options.message = response.statusText
        options.description = response.data
        Message.error(options) // 呼叫全域性元件提示
          location.href = '/login'
      }else if (status === 200){
        // custom error
        if (response.data['<isError>']){
          ...
        }
        //timeout
        else if(data.data && data.data['ecode'] === "401"){
          ....
        }
      }
    });
  });
}複製程式碼

auth0.com/blog/ten-th…關於Token,你需要知道的十件事.

  • Token 應該被儲存起來,放到 local / session stograge 或者 cookies.

      1. 在單頁應用程式中,有些使用者重新整理瀏覽器後會帶來一些跟 token 相關的問題。而解決方法很簡單:你應該把 token 儲存到起來:放到 session storage, local storage 或者是客戶端的 cookie 裡。而瀏覽器不支援 session storage 時都應該轉存到 Cookies 裡。
      2. 存放在Cookie裡面,只是把 Cookie 當作一個儲存機制,而不是一種驗證機制,這個 cookie 不會被 Web 框架用於使用者驗證,所以沒有 XSRF 攻擊的危險。複製程式碼
  • Tokens像 cookie 一樣有有效期,你可以有更多的操作方法
// Cookie的有效期操作

1. cookies 可以在瀏覽器關閉後刪除(session cookies);
2. 通過絕對有效期或彈性有效期(sliding window expiration);
3. Cookies 可以通過攜帶有有效期地儲存起來。複製程式碼
//一旦 token 過期,只需要重新獲取一個。我們一般定義個可以介面去重新整理 token


 1. 讓舊的 token 失效;
 2. 檢查這個使用者是不是還存在,許可權是否被取消或者任何對你的程式來說是有必要的;
 3. 得到一個更新了有效期的 token。複製程式碼
  • Local / session storage 不會跨域工作,請使用一個標記 cookie

      1. sessionStorage 不能跨頁面共享的,關閉視窗即被清除,
      2. localStorage 可以同域共享,並且是持久化儲存的
      3. 在 local / session storage 的 tokens,就不能從不同的域名中讀取,甚至是子域名也不行.
      解決辦法使用Cookie.demo: 假設當使用者通過 app.yourdomain.com 上面的驗證時你生成一個 token 並且作為一個 cookie 儲存到 .yourdomain.com,然後,在 youromdain.com 中你可以檢查這個 cookie 是不是已經存在了,並且如果存在的話就轉到 app.youromdain.com去。這個 token 將會對程式的子域名以及之後通常的流程都有效(直到這個 token 超過有效期)
      只是利用cookie的特性進行儲存而非驗證.複製程式碼
  • 每個 CORS(跨域資源共享)請求都會帶上預請求(Preflight request)

  • 當你需要流傳送某些東西,請用 token 去獲取一個已簽名的請求。

  • XSS 比 XSRF 要更容易防範
XSS 攻擊的原理是,攻擊者插入一段可執行的 JavaScripts 指令碼,該指令碼會讀出使用者瀏覽器的 cookies 並將它傳輸給攻擊者,攻擊者得到使用者的 Cookies 後,即可冒充使用者。
但是要防範 XSS 也很簡單,在寫入 cookies 時,將 HttpOnly 設定為 true,客戶端 JavaScripts 就無法讀取該 cookies 的值,就可以有效防範 XSS 攻擊。
因為 Tokens 也是儲存在本地的 session storage 或者是客戶端的 cookies 中,也是會受到 XSS 攻擊。所以在使用 tokens 的時候,必須要考慮過期機制,不然攻擊者就可以永久持有受害使用者帳號。複製程式碼
  • 注意 token 的大小

      1. Token 機制在每次請求 API 的時候,都需要帶上一個 Authorization 的 Http Header 。
      2. Token 的大小其實由你儲存在 token 中的資訊量所決定,例如可能有 nickname,openid 等開發者另外加上的資訊。
      3. Token 中只保留關鍵的幾條身份標識資訊,其餘都放到資料庫裡面了,許可權控制的時候再撈出。這樣做的好處是,開發者可以完全掌控 token,因為關鍵資訊都已經是你程式碼和資料庫中的一部分了,想怎麼弄都可以了
      4. # Token
          GET /foo
          Authorization: Bearer ...2kb token...複製程式碼
  • 有需要的話,要加密並且簽名 token
  • 將 JSON Web Tokens 應用到 OAuth 2,關於OAuth驗證阮一峰大神部落格有.
  • Tokens 不是萬能的解決方法,得根據你的需求自行採用

ps : 有些地方還是不懂,慢慢學.

相關文章