JWT Token 记住登入帐号 Remember me

验证进阶知识: JWT Token 记住登入帐号

JWT Token 没有提供 Remember Token 的功能

若要在 JWT Token 提供 Remember Token 的功能,可以将储存在 Cookie 的 JWT Token 时间效期拉很长,当 Cookie 存在就可以正常的去做验证登入功能

使用 JWT Token Refresh Token 机制

JWT Token 会产生一个有效期的 Token,而 Token 中会包含以下栏位

栏位 说明
iat Token 产生时间
exp Token 最后可用时间,在此时间内 token 都可以重新 refresh 取得
nbf Token 有效时间,超过此时间 Token 会失效
/* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGgua2VqeXVuLmNvbS9hcGkvdjEvdXNlci9hdXRoL2xvZ2luIiwiaWF0IjoxNjIxMzIyMDg2LCJleHAiOjE2MjE0MDg0ODYsIm5iZiI6MTYyMTMyMjA4NiwianRpIjoiSzRzbzNmeWJsMjBjUnFjeCIsInN1YiI6InVzZXItc2V1azU4ODN6bXY1YXV1In0.EeB6mb-XWU9Yhq9UroKeI6SNiiC6taa7Jo5FF8jzrhc
*/
{
  "iss": "https://auth.kejyun.com/api/v1/user/auth/login",
  "iat": 1621322086,
  "exp": 1621408486,
  "nbf": 1621322086,
  "jti": "K4so3fybl20cRqcx",
  "sub": "user-seuk5883zmv5auu"
}

exp 栏位时间会大于或等于 nbf时间,当时间超过 nbf 时间时此 Token 会无法使用,但若 nbf 时间在 exp 时间内,可以重新使用 refresh 的方式再取得有效的 Token,直到时间超过 exp 为止

此 Token 会透过 JWT 金钥去验证资料是否有被串改过,所以可以保护 Token 的安全性,所以可以将 JWT Token 的过期时间 nbf 设定为比较短,而 JWT Token 可用时间 exp 设定长一点,当 Token 过期可以重新得去 Refresh Token 就可以持续不断延长 Token 可用时间

步骤 流程 用途
1 传入帐号密码验证 验证帐号密码是否正确,资料库是否有此帐号
2 记录使用者 user_id 到 JWT Token Cookie 告诉前端此使用者的身份是谁,之后会透过这个含有 user_id 的 JWT Token cookie 做验证
3 透过含有 user_id 的 JWT Token Cookie 做其他验证请求 使用金钥验证 Token 是否合法没有被串改,验证合法则捞取 JWT Token Cookie 中的 user_id 捞取使用者资料
4 呼叫 Refresh Token API 取得新的 JWT Token 储存至 Cookie 若 JWT Token 失效,但 exp 还在效期内,重新 Refresh 取得新的 Refresh JWT Token
5 使用新的 JWT Refresh Token 做验证请求 透过新的 Refresh Token 重新验证取得登入使用者资料

JWT Token 效期过长安全性问题

当将 JWT Token 效期设定比较长,可以达到记住登入使用者帐号,让使用者保持随时是登入的状态,但若时间设定过长(e.g. 3 年、5 年)则 Token 安全性会有问题,若此 Token 被劫取走,在这个这麽长的有效期限内,此 Token 都会是有效的可以合法的存取 API

JWT Token 加入 remember_token

在使用者资料表加入一个 remember_token 的栏位,当作帮使用者做重新产生 JWT Token 验证的动作,所以登入流程会变成

步骤 流程 用途
1 传入帐号密码验证 验证帐号密码是否正确,资料库是否有此帐号
2 产生新的 remember_token 记录到使用者资料表的 remember_token 栏位 做为之后验证重新登入用
3 记录使用者 user_id 及 remember_token 到 JWT Token Cookie 告诉前端此使用者的身份是谁,之后会透过这个含有 user_id 的 JWT Token cookie 做验证
4 透过含有 user_id 及 remember_token 的 JWT Token Cookie 做其他验证请求 使用金钥验证 Token 是否合法没有被串改,验证合法则捞取 JWT Token Cookie 中的 user_id 捞取使用者资料
5 呼叫 Refresh Token API 取得新的 JWT Token 储存至 Cookie 若 JWT Token 失效,但 exp 还在效期内,重新 Refresh 取得新的 Refresh JWT Token
6 使用新的 JWT Refresh Token 做验证请求 透过新的 Refresh Token 重新验证取得登入使用者资料
7 透过 remember_token 及 user_id 的 Cookie 做重新取得新 JWT Token 捞取 JWT Cookie 中的 remember_token 及 user_id,与资料库做比对,确认是否 token 合法可以正常重新产生
8 使用新产生的 JWT Token 做验证请求 透过新产生的 JWT Token 重新验证取得登入使用者资料
/* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGgua2VqeXVuLmNvbS9hcGkvdjEvdXNlci9hdXRoL2xvZ2luIiwiaWF0IjoxNjIxMzIyMDg2LCJleHAiOjE2MjE0MDg0ODYsIm5iZiI6MTYyMTMyMjA4NiwianRpIjoiSzRzbzNmeWJsMjBjUnFjeCIsInN1YiI6InVzZXItc2V1azU4ODN6bXY1YXV1IiwicmVtZW1iZXJfdG9rZW4iOiJyYW5kb20tcmVtZW1iZXItdG9rZW4ifQ.GoW1zQ70ncIox--G1zrurNhEmTTpqWV_2d-2gWWWsow */
{
  "iss": "https://auth.kejyun.com/api/v1/user/auth/login",
  "iat": 1621322086,
  "exp": 1621408486,
  "nbf": 1621322086,
  "jti": "K4so3fybl20cRqcx",
  "sub": "user-seuk5883zmv5auu",
  "remember_token" : "random-remember-token"
}

当 JWT Token 效期时间很短时(例如 300 分钟),在 JWT Token 过期时,也可以透过 Cookie 中的 remember_token 去重新验证并产生新的 JWT Token 回传给使用者,让使用者可以持续使用合法的 JWT Token 不断做存取

remember_token 安全性

因为只要 JWT Token Cookie 过期时间设定的够长,只要一直有 remember_token,则使用者就可以一直无限期的一直不断的维持登入状态,这样可能会有安全性的问题,所以在使用者自己触发登出时,记得更新储存在资料库的 remember_token,让其他有此 remember_token 的使用者无法继续登入

参考资料