首先,請注意,令牌過期和吊銷是兩個不同的過程。
- 到期僅發生在Web應用程序上,而不發生在本機移動應用程序上,因為本機應用程序永不到期。
- 僅當(1)使用單擊網站或本機Apps上的注銷按鈕;(2)用戶重設密碼;以及 (3)用戶在管理面板中明確撤銷其令牌。
1.如何讓JWT到期
如果JWT令牌被盜,那么永不過期的令牌是危險的,這樣有人總是可以訪問用戶的數據。
引用JWT RFC:
“ exp”(到期時間)聲明標識了在其上或之后不得接受JWT進行處理的到期時間。“ exp”聲明的處理要求當前日期/時間必須早於“ exp”聲明中列出的到期日期/時間。
因此答案很明顯,exp
如果聲明中的日期exp
早於當前日期,則在聲明中設置到期日期並在服務器端拒絕令牌。
很容易,對吧?
問題是移動應用程序永不過期,例如,人們可以在一個月后重新打開該應用程序,而無需再次登錄。
-
對於Web Apps:如果將到期時間設置為1周,則請勿在1周內使用令牌。請在不到一周的時間內使用它,並在舊令牌過期之前獲取一個新令牌。例如,使瀏覽器在第六天發出交換新令牌的請求。這與會話和cookie的常規概念沒有什么不同。
因此,在服務器端,創建一個名為Restful的API
/token/extend
,如果給定了有效的令牌,它將返回一個新的令牌。如果用戶有一個星期不使用您的應用程序,那么下次他進入您的應用程序時,他將不得不再次登錄,這很好並且被廣泛接受。
-
對於本機移動應用程序:您可以使用上面說明的相同方法,但是現在這不是移動應用程序的工作方式,例如,用戶可以在一個月不使用Facebook應用程序之后打開它,而下次打開他不需要的應用程序時重新登錄。
一種解決方案是添加命名
aud
為JWT令牌的受眾聲明,例如,使用有效負載,例如{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "aud":"iPhone-App"}
。在服務器端,如果令牌具有一個aud
具有值的字段,iPhone-App
則忽略exp
聲明,以使令牌iPhone-App
永不過期。但是,您仍然可以使用第2節中描述的方法來撤銷此類令牌。另一個解決方案是使用永不過期的刷新令牌來獲取確實過期的新JWT令牌。由於刷新令牌永不過期,如果您的手機被盜怎么辦?同樣,刷新令牌仍然是有效的JWT令牌,您可以使用第2節中介紹的方法撤消刷新令牌。
通常,為了區分一個用戶的不同刷新令牌,一個好的做法是將特定的設備名稱放入刷新令牌中,例如
{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "device":"Frank's iPhone"}
,這樣,當用戶想要撤消刷新令牌時,他可以知道正在使用此刷新令牌。在他的iPhone上。
2.如何撤銷JWT令牌
有時,用戶需要撤消令牌,例如,單擊注銷按鈕或更改密碼。
假設每個用戶都有多個設備,例如一個瀏覽器,一個本機iPhone APP和一個本機Android APP。
有三種方法:
-
更改密鑰。
這將撤消所有用戶的所有令牌,這是不可接受的。
-
使每個用戶都有自己的機密,只需更改指定用戶的機密即可。
現在,RESTful后端不再是無狀態的。每當請求進入服務器時,服務器都需要查詢數據庫以獲取用戶的秘密。
為了獲得更好的性能,我們將對存儲
(user, secret)
在Redis中而不是MySQL中,使用username
鍵作為鍵,secret
將值用作值。這種方式將撤消一個用戶的所有令牌,雖然效果更好,但仍然不夠好。
-
將已撤銷的JWT令牌存儲在Redis中。
使用令牌作為鍵,值始終為boolean
true
。令牌將僅存儲特定時間段(即聲明中的時間)
exp
,在到期時間之后將被從Redis中刪除。這樣一次只能撤銷一個令牌,完美!
有關更多詳細信息,請參閱此博客,使用Redis撤消從jsonwebtoken生成的令牌。
歡迎提出建議,如果我錯了,請糾正我。
3.如何安全地使用JWT令牌
首先,始終使用HTTPS來確保通過網絡傳輸JWT令牌是安全的。通過使用HTTPS,沒有人可以通過網絡嗅探用戶的JWT令牌。
其次,確保JWT令牌安全地存儲在用戶的Android,iOS和瀏覽器上。
- 對於Android,將令牌存儲在KeyStore中
- 對於iOS,將令牌存儲在KeyChain中
- 對於瀏覽器,請使用
HttpOnly
和Secure
cookie。曲奇餅。該HttpOnly
標志可防止Cookie被JavaScript訪問,並防止XSS攻擊。該Secure
標志僅允許將cookie通過HTTPS連接發送到服務器。
只要我們確保瀏覽器,用戶設備和令牌的傳輸安全,就不再需要令牌吊銷機制,我們仍然可以使RESTful服務保持無狀態。