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 的使用者无法继续登入
参考资料
- security - What is the best way to implement “remember me” for a website? - Stack Overflow
- API Authentication Workflow with JWT and Refresh Tokens - DEV Community
- Remember Me and Forgot Password functionality in JWT Auth · Issue #261 · tymondesigns/jwt-auth · GitHub
- JWT Authentication
Donate KJ 贊助作者喝咖啡
如果這篇文章對你有幫助的話,可以透過下面支付方式贊助作者喝咖啡,如果有什麼建議或想說的話可以贊助並留言給我
If this article has been helpful to you, you can support the author by treating them to a coffee through the payment options below. If you have any suggestions or comments, feel free to sponsor and leave a message for me!
方式 Method | 贊助 Donate |
PayPal | https://paypal.me/kejyun |
綠界 ECPay | https://p.ecpay.com.tw/AC218F1 |
歐付寶 OPay | https://payment.opay.tw/Broadcaster/Donate/BD2BD896029F2155041C8C8FAED3A6F8 |