中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring?Boot怎么集成JWT實現前后端認證

發布時間:2022-04-13 10:09:49 來源:億速云 閱讀:189 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Spring Boot怎么集成JWT實現前后端認證”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Spring Boot怎么集成JWT實現前后端認證”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

JWT簡介

JWT(全稱:Json Web Token)是一個開放標準(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對象在各方之間安全地傳輸信息。

為什么要用JWT

傳統session認證存在那些弊端?

  • 每個用戶的登錄信息都會保存到服務器的Session中,隨著用戶的增多,服務器開銷會明顯增大。

  • Session的信息存放在服務器的內存中,對于分布式應用會導致失效,雖然可以將session的信息統一存放在Redis的緩存中,但這樣可能增加了復雜性。

  • 由于Session認證是基于Cookie實現,而針對于非瀏覽器端和手機的移動端都不適用。

  • 前后端分離系統,由于前后端存在跨域,而Cookie信息無法跨越,所以采用Session認證也是無法繼續寧跨域認證。

JWT認證的優勢

  • 簡潔:JWT Token數據量小,傳輸速度也很快。

  • 跨語言: JWT Token是以JSON加密形式保存在客戶端的,所以JWT是跨語言的,任何web形式都支持。 跨平臺:不依賴于cookie和session,無需將session信息存放在服務端,非常適合于分布式應用,應用于擴展。

JWT的數據結構

Spring?Boot怎么集成JWT實現前后端認證

Header

JWT第一部分是頭部分,它是一個描述JWT元數據的Json對象,通常如下所示。

{
    "alg": "HS256",
    "typ": "JWT"
}

alg屬性表示簽名使用的算法,默認為HMAC SHA256(寫為HS256),typ屬性表示令牌的類型,JWT令牌統一寫為JWT。

Payload

JWT第二部分是Payload,也是一個Json對象,除了包含需要傳遞的數據,還有七個默認的字段供選擇。 iss:發行人 exp:到期時間 sub:主題 aud:用戶 nbf:在此之前不可用 iat:發布時間 jti:JWT ID用于標識該JWT

{
    //默認字段
    "sub":"主題123",
    //自定義字段
    "name":"java",
    "isAdmin":"true",
    "loginTime":"2021-12-05 12:00:03"
}

需要注意的是,默認情況下JWT是未加密的,任何人都可以解讀其內容,因此如果一些敏感信息不要存放在此,以防信息泄露。JSON對象也使用Base64 URL算法轉換為字符串保存。

Signature

簽名哈希部分是對上面兩部分數據簽名,需要使用base64編碼后的header和payload數據,通過指定的算法生成哈希,以確保數據不會被篡改。

Spring Boot集成JWT

引入Jwt包

<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
  </dependency>

編寫jwt工具類

public class JwtUtil
{
//創建jwt
public static String createJWT(String subject, String issue, Object claim,
            long ttlMillis)
    {
       //當前時間
        long nowMillis = System.currentTimeMillis();
        //過期時間
        long expireMillis = nowMillis + ttlMillis;
        String result = Jwts.builder()
                .setSubject(subject) //設置主題
                .setIssuer(issue) //發行者
                .setId(issue)//jwtID
                .setExpiration(new Date(expireMillis)) //設置過期日期
                .claim("user", claim)//主題,可以包含用戶信息
                .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法
                .compressWith(CompressionCodecs.DEFLATE).compact();//對載荷進行壓縮

        return result;
    }
    
    // 解析jwt
    public static Jws<Claims> pareseJWT(String jwt)
    {
        Jws<Claims> claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt);
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }

   //獲取主題信息
    public static Claims getClaims(String jwt)
    {
        Claims claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt).getBody();
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }
  }
  
   /**
     * 獲取密鑰
     * 
     * @return Key
     */
    private static Key getSignedKey()
    {
        byte[] apiKeySecretBytes = DatatypeConverter
                .parseBase64Binary(getAuthKey());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes,
                getSignatureAlgorithm().getJcaName());
        return signingKey;
    }
    
    private static SignatureAlgorithm getSignatureAlgorithm()
    {
        return SignatureAlgorithm.HS256;
    }
  
  //獲取密鑰,可以動態配置
  public static String getAuthKey()
  {
        String auth = "123@#1234";
  }

Token認證攔截器

 Component
public class TokenInterceptor extends HandlerInterceptorAdapter
{
    public static Log logger = LogManager.getLogger(TokenInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception
    {
        String uri = request.getRequestURI();
        logger.info("start TokenInterceptor preHandle.." + uri);
         
		//需要過濾特殊請求
        if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri))
        {
            return true;
        }
        
		
        String metohd=request.getMethod().toString();
        logger.info("TokenInterceptor request method:"+metohd);
        //options 方法需要過濾
        if("OPTIONS".equals(metohd))
        {
            return true;   
        }
        
		//是否開啟token認證
        boolean flag = SystemUtil.getVerifyToken();
        ResponseResult result = new ResponseResult();
		//從請求的head信息中獲取token
        String token = request.getHeader("X-Token");

        if (flag)
        {
            if(StringUtils.isEmpty(token))
            {
                token=request.getParameter("X-Token");    
            }
            // token不存在
            if (StringUtils.isEmpty(token))
            {
                result.setCode(ResultCode.NEED_AUTH.getCode());
                result.setMsg(ResultCode.NEED_AUTH.getMsg());
                WebUtil.writeJson(result, response);
                return false;
            }
            else
            {
                Claims claims = JwtUtil.getClaims(token);
                String subject = "";
                if (claims != null)
                {
                    subject = claims.getSubject();
                    // 驗證主題
                    if (StringUtils.isEmpty(subject))
                    {
                        result.setCode(ResultCode.INVALID_TOKEN.getCode());
                        result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                        WebUtil.writeJson(result, response);
                        return false;
                    }								
                }
                else
                {
                    result.setCode(ResultCode.INVALID_TOKEN.getCode());
                    result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                    WebUtil.writeJson(result, response);
                    return false;
                }
            }
        }
        return true;
    }

}

配置攔擊器

@Configuration
public class WebConfig implements WebMvcConfigurer
{
    @Resource
    private TokenInterceptor tokenInterceptor;

    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
    }
 }

登錄驗證流程

Spring?Boot怎么集成JWT實現前后端認證

示例代碼

@RequestMapping("login")
public Result login(HttpServletResponse response)
{
    Map<String, Object> map = new HashMap<>();
    //
    Result result = loginAuth(user);
    int code = result.getCode();
            //登錄認證成功
    if (code ==ResultCode.SUCCESS)
    {
        //默認為7天
        Long ttlMillis = 7*1000 * 60 * 60 * 24;
        //過期時間
        long expreTime = System.currentTimeMillis() + ttlMillis;
        String tokenKey = UUID.randomUUID().toString();
        String tokenId = JwtUtil.createJWT(user.getUserId(), tokenKey,
                user.getPassword(), expreTime);                   
        map.put("expreTime", expreTime);				
        map.put("tokenId", tokenId);           
    }
    else
    {
        logger.error("login error:" +FastJsonUtil.toJSONString(result));
    }
    return result;
}

讀到這里,這篇“Spring Boot怎么集成JWT實現前后端認證”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

青州市| 怀化市| 合水县| 遂宁市| 丰台区| 洛阳市| 资兴市| 郁南县| 海宁市| 连江县| 东丰县| 稷山县| 深州市| 道孚县| 龙门县| 高淳县| 丁青县| 明光市| 沙雅县| 连州市| 贵南县| 岳普湖县| 定州市| 尼勒克县| 平乡县| 湘潭市| 鹤壁市| 抚松县| 固始县| 永康市| 淄博市| 天等县| 永济市| 社会| 江华| 阿勒泰市| 海原县| 大姚县| 博湖县| 比如县| 中牟县|