jwt實現註冊與登陸系統

前言

自己用react+koa實現了一個包含登陸和註冊功能的網址,在這裏記錄一下實現過程
項目地址:github地址
預覽地址:預覽地址


註冊

註冊其實沒什麼好說的,就是要注意不要明文保存密碼,否則數據庫泄露後,密碼會被其他人用來撞庫使用。
前臺加密主要是爲了防止post請求明文傳遞密碼,本來我想在前端加密,然後數據庫直接保存加密的密碼到數據庫,登陸時傳遞加密後的密碼進行登陸,但是前端使用的加密工具加密同一個密碼每次都生成不同的結果,導致每次查詢都是密碼不正確,我只能在後端先解密前端密碼,然後換用了一個加密工具,加密同一個密碼生成相同的結果,這樣查詢密碼纔會正確。



登陸

傳統的登錄系統是通過cookiesession做的登錄,這種登錄需要後端記錄session,當在線用戶很多時,會增加服務器壓力,這裏我使用JSON Web Token (JWT)更好的方式來做登錄(後端不需要記錄任何東西)。關於cookie、session、token的概念我簡單的總結過,具體可以參考這裏

簡述登錄流程:

  1. 用戶使用賬號密碼登錄
  2. 後臺驗證賬號密碼是否正確,正確則生成token併發送給前臺。
  3. 前臺存儲token並在下次訪問傳遞給後臺
  4. 後臺驗證前臺傳過來的token是否正確,不正確則返回錯誤給前臺,讓他重新登錄

實際上我們需要解決以下問題就可以實現一個登陸:

  1. 後臺如何生成token?
  2. 前臺如何保存token,並傳遞給後臺?
  3. 既然後臺不保存任何信息,後臺如何驗證token?如何知道token不是僞造的

舉個簡單的例子:
我有個箱子要送出去,我自己不記錄我送了哪些箱子,別人送回來的時候我怎麼知道這是我的箱子?
很簡單,我給箱子上把鎖,別人還回來的時候,我用我自己的鑰匙打開,能打開就是我的箱子,否則就不是。
生成token時,我們可以將用戶名通過某種加密算法加密生成一個串字符串,解密時再用加密算法還原,如果可以還原就證明這個token有效,否則無效。

jsonwebtoken

我自己使用jsonwebtoken來生成和解析token,下面是一個簡單的使用

const jwt = require('jsonwebtoken');

const secert = 'secert_key'                   //相當於鑰匙,這個鑰匙不要讓其他人知道,否則別人會拿這個生成有效token

//加密,根據secert加密生成token
const token = jwt.sign({username:'zzh'},secert)   
console.log('token',token)

//解密,如果token正確會還原,否則會拋出錯誤
try {
    const result = jwt.verify(token,secert)     
    console.log(result)
} catch (error) {
    console.log(error)
}

上面就是一個加密和解密的過程,這就實現token的驗證。我們在登錄正確時,將用戶名或id用上面的方法加密生成token,並返回給前臺,前臺用某種方式存儲(SessionStorage、LocalStorage),然後前端可以放在請求頭中傳遞給後臺,後臺再驗證token是否正確。

koa-jwt

直接使用上面的jsonwebtoken太麻煩了,我們需要自己對接口進行token驗證和驗證失敗的處理。可以使用koa-jwt中間件來幫我們完成這些功能,我只需要會用即可。

//app.js
...
var jwt = require('koa-jwt');

app.use(jwt({ secret: 'secert_key' }).unless({ path: [/^\/public/] }));

當我們使用koa-jwt中間件後,app會自動去驗證token,當token不存在或token失效時,會拋出401錯誤。另外我們要注意幾點:

  • 生成token時還是用的jsonwebtoken進行加密的(koa-jwt自帶jsonwebtoken依賴)
  • 加密和解密的secret必須一樣(不要泄露)
  • koa-jwt默認是從請求頭的Authorization中尋找token,如果需要以其他方式傳遞token則自行根據官網設置。Authorization:'Bearer ’ + token
  • 要設置不需要驗證token的接口,比如登陸接口是不需要驗證token的(通過unless設置)

關於koa-jwt的使用可以看github文檔或這個demo

下面幾個問題可以思考
token存在前端什麼位置合適?
可以存在SessionStorage、LocalStorage、cookie中。

前端根據什麼判斷是否登錄?
當登陸成功時存儲token到cookie中,然後判斷cookie中是否有token

如何防止token被盜,然後繞過登陸的問題?
這樣有個問題,我可以通過瀏覽器的調試工具拿到token,然後在其他地方不登錄,在瀏覽器的調試工具手動設置token到cookie或storage中去,這樣就繞過了登錄。這其實是jwt的一個弊端,只要是一個正確的token,服務器都認爲是有效的。解決的方法可以用https或者將token有效時間縮短。

cookie的httpOnly只能防止前端讀取cookie,但是不能限制前端設置cookie

如何在退出登錄時使token失效?
可以將用過的token加入黑名單,這樣不管是退出登錄還是竊取別人的token使用都不會登錄成功

如何防止同個賬號同時登錄?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章