SpringBoot中使用 JWT + 攔截器實現登錄驗證


舊的方法存在缺點

之前的策略是,UUID + redis + 攔截器的思路。

服務器端在驗證 roomid 和 password相匹配之后,使用 UUID 生成一個字符串作為 token ,接着往 Redis 服務中寫入一個映射(token, roomid), 設置過期時間為20分鍾, 並且把token 通過響應返回給客戶端。因此,客戶端便可以使用這個 UUID 產生的 token 來訪問。

對於需要攜帶 token 的請求,安排了一個攔截器來檢查這些請求,檢驗請求所攜帶的 token 與 roomid 是否與 Redis 中已有的映射相匹配,若匹配,說明已經授權可以可以放行,若不匹配,則拒絕請求。

缺點在於:

  • 服務器端需要使用 Redis 保存許多鍵值對,占用一定的內存空間。
  • 客戶端獲取的值是單純的值,當用戶太多時,UUID 的數目變得過多會加大被猜中的概率。

JWT

token 的三部分中,第一部分是頭,第二部分是負載,第三部分是簽名,一二部分都是base64加密,不能存放敏感信息。
如果客戶端私自修改過期時間,token 的驗證環節可以檢測出來。(有使用密鑰對過期時間進行加密)
如果修改客戶端 roomid,是否意味着可以冒用他人的 token?token 生成過程有把負載部分考慮在內,驗證的時候可以驗證出負載被修改。
使用 JWT 是用時間換空間,節省了服務端的空間。

使用 JWT(JSON Web Token) 的方法

maven 中添加依賴,引入 Java-jwt 項目。

<dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.18.2</version>
</dependency>

服務器有一個不能公開的密鑰。

服務器端在驗證 roomid 和 password 之后,Token 簽名算法使用密鑰根據 payload 的內容生成簽名,可以配置token 的過期時間(本項目配置的是 1 小時),token 的生成相當於服務器對驗證通過者的授權,授權其可進行 1 小時的免密碼暢行。最終得到一個 token 通過響應返回給客戶端。 客戶端可以使用這個 token 進行請求。

對於需要攜帶 token 的請求,安排了一個攔截器進行檢查,使用 token 校驗算法來檢查請求所攜帶的 token的簽名是否有效(過期或者 roomid 與簽名內容不匹配都會被認為無效)。若 token 檢驗正確,則放行,若檢驗錯誤,則拒絕請求。

下方是 token 的生成與驗證,其中 secret 是自己設定的密鑰(是一個字符串,我的密鑰可不能公開貼出來)。

token 生成過程:

 public static String generate(String roomid){
        String token = "";
        try{
            Algorithm algorithm = Algorithm.HMAC256(secret);
            Map<String,Object> map = new HashMap<>();
            map.put("roomid",roomid);
            token = JWT.create().withIssuer("auth0")
                    .withPayload(map)
                    .withExpiresAt(new Date(System.currentTimeMillis() + (long)3600*1000))
                    .sign(algorithm);
        }catch(JWTCreationException e){
            e.printStackTrace();
        }
        return token;
    }

token 的驗證,驗證通過則返回 roomid,驗證不通過則返回 null。

public static String validate(String roomid, String token){
        DecodedJWT jwt = null;
        try{
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier jwtVerifier = JWT.require(algorithm)
                    .withClaim("roomid",roomid)
                    .withIssuer("auth0").build();
            jwt = jwtVerifier.verify(token);
            if (jwt == null )return null;
            Claim claim = jwt.getClaim("roomid");
            if (claim == null )return null;
            return claim.asString();
        }catch (JWTVerificationException e){
            return null;
        }

    }

參考代碼:https://github.com/auth0/java-jwt


免責聲明!

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



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