天天看點

JWT實作使用者權限認證

網上的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