網上的java基礎教程曾教會我們,将使用者登入資訊存在session(伺服器端)中,需要驗證的時候拿出來作對比以達到身份
驗證的效果。但這種方式暴露的問題也是可想而知的:
1.Seesion:每次認證使用者發起請求時,伺服器需要去建立一個記錄來存儲資訊。當越來越多的使用者發請求時,記憶體的開銷也會不斷增加。
2.可擴充性:在服務端的記憶體中使用Seesion存儲登入資訊,伴随而來的是可擴充性問題。
3.CORS(跨域資源共享):當我們需要讓資料跨多台移動裝置上使用時,跨域資源的共享會是一個讓人頭疼的問題。在使用Ajax抓取另一個
域的資源,就可以會出現禁止請求的情況。
4.CSRF(跨站請求僞造):使用者在通路網站時,他們很容易受到跨站請求僞造的攻擊,并且能夠被利用其通路其他的網站。
在這些問題中,可擴充行是最突出的。是以我們有必要去尋求一種更有行之有效的方法。
而token卻能解決在服務端存儲資訊時的許多問題:
1.使用者登入
和往常一樣,一個表單,輸入使用者名、密碼然後登入
<form action="servlet/Addcookies" method="post">
<label>賬 号:</label><input type="text" name="username" /><br>
<label>密 碼:</label><input type="password" name="password" /><br>
<button type="submit">登入</button>
</form>
可以看到,這個表單送出到一個servlet
2.servlet
下面看這個servlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String Token = null;
try {
Token = JwtToken.creatToken(username);
} catch (Exception e) {
e.printStackTrace();
}
Cookie cookie = new Cookie("token", Token);
cookie.setPath("/"); // 設定路徑使得cookie共享
cookie.setMaxAge(1000);// 設定cookie有效期
response.addCookie(cookie);// 向用戶端添加cookie
response.sendRedirect("../index2.jsp");// 請求轉發
}
根據表單發來的請求,擷取username參數值;
根據username參數值生成Token(具體方法後面講);
建立一個cookie,key值為token,value值為之前生成的Token;
頁面跳轉到index2.jsp。
3.index2.jsp
頁面沒什麼,直接看js
//定義一個function,根據name擷取該cookie的value值
function getCookie(name){
//擷取cookies并分割成數組形式
var strcookie = document.cookie;
var arrcookie = strcookie.split("; ");
//周遊所有cookie,并根據參數傳回對應cookie的vaule
for ( var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split("=");
if (arr[0] == name){
return encodeURIComponent(arr[1]);
}
}
return "找不到指定cookie或cookie過期了";
}
var token=getCookie("token");
document.getElementById("go").innerHTML=token;
這樣,就将存在cookie裡面的token拿到了,之後需要驗證使用者權限的話,就将這個token作為參數放到請求中;
服務端接收到這個攜帶token的請求,會對token解析,如果解析成功,就表示權限認證通過。
4.Token的生成與解析
直接看這個工具類
package com.eco.util;
import java.util.HashMap;
import java.util.Map;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JwtToken {
/* 生成token加密所需的公鑰,位于服務端 */
public static String SECRET = "eco";
/*
* 根據使用者登入資訊(使用者名、密碼)生成token
*
* @pram name 使用者請求提供的某個參數
*/
public static String creatToken(String name) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = JWT.create().withHeader(map).withClaim("name", name)
.sign(Algorithm.HMAC384(SECRET));
return token;
}
/*
* 解析使用者請求提供的token字元串,傳回map
*
* @pram token 使用者請求提供的token
*/
public static Map<String, Claim> verifyToken(String token) throws Exception {
JWTVerifier verifier = JWT.require(Algorithm.HMAC384(SECRET)).build();
DecodedJWT jwt = null;
jwt = verifier.verify(token);
return jwt.getClaims();
}
}
轉載于:https://www.cnblogs.com/eco-just/p/8633310.html