使用JWT實(shí)現(xiàn)Token認(rèn)證

為什么使用JWT?
隨著技術(shù)的發(fā)展,分布式web應(yīng)用的普及,通過session管理用戶登錄狀態(tài)成本越來越高,因此慢慢發(fā)展成為token的方式做登錄身份校驗(yàn),然后通過token去取redis中的緩存的用戶信息,隨著之后jwt的出現(xiàn),校驗(yàn)方式更加簡單便捷化,無需通過redis緩存,而是直接根據(jù)token取出保存的用戶信息,以及對(duì)token可用性校驗(yàn),單點(diǎn)登錄更為簡單。

JWT架構(gòu)圖


JWT架構(gòu)圖.png

使用JWT核心代碼:
maven依賴:

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

JWT工具類:
用于生成Token,和Token驗(yàn)證

public class JwtUtils {
    /**
     * 簽發(fā)JWT
     * @param id
     * @param subject 可以是JSON數(shù)據(jù) 盡可能少
     * @param ttlMillis
     * @return  String
     *
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主題
                .setIssuer("user")     // 簽發(fā)者
                .setIssuedAt(now)      // 簽發(fā)時(shí)間
                .signWith(signatureAlgorithm, secretKey); // 簽名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 過期時(shí)間
        }
        return builder.compact();
    }
    /**
     * 驗(yàn)證JWT
     * @param jwtStr
     * @return
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
    
    /**
     * 
     * 解析JWT字符串
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(jwt)
            .getBody();
    }
}

如何使用?
代碼實(shí)例:

public class LoginController {
    @Autowired
    UserRepository userRepository;
    
    @ApiOperation(value="用戶登陸")
    @RequestMapping(value="login",method = RequestMethod.POST)
    public ReturnVo login(String username, String password,HttpServletResponse
            response) {
        User user =  userRepository.findByUsername(username);
        if(user!=null){
            if(user.getPassword().equals(password)){
                //把token返回給客戶端-->客戶端保存至cookie-->客戶端每次請(qǐng)求附帶cookie參數(shù)
                String JWT = JwtUtils.createJWT("1", username, SystemConstant.JWT_TTL);
                return ReturnVo.ok(JWT);
            }else{
                return ReturnVo.error();
            }
        }else{
            return ReturnVo.error();
        }
    }
    @ApiOperation(value="獲取用戶信息")
    @RequestMapping(value="description",method = RequestMethod.POST)
    public ReturnVo description(String username) {
        User user =  userRepository.findByUsername(username);
        return ReturnVo.ok(user.getDescription());
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,869評(píng)論 18 139
  • 【問】xgboost/gbdt在調(diào)參時(shí)為什么樹的深度很少就能達(dá)到很高的精度? 用xgboost/gbdt在在調(diào)參的...
    Ten_Minutes閱讀 2,355評(píng)論 2 2
  • 萬歷十五年 完結(jié) 世間很多殘酷的事都用道德的名義去施行,也是中外古今一律。這篇文章以發(fā)揚(yáng)積極性的精神為主,也用不著...
    Aero小白閱讀 258評(píng)論 0 0
  • 想說的很多,但是現(xiàn)在我只想說你特么就是個(gè)王八,直男癌,真以為自己有多牛逼呢!小矮子一個(gè),還各種臟話在口,是,我剛開...
    huayaaa閱讀 346評(píng)論 0 0