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();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM