欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

SpringSecurityJwtToken如何實現(xiàn)自動刷新

這篇文章主要為大家展示了SpringSecurity Jwt Token如何實現(xiàn)自動刷新,內(nèi)容簡而易懂,希望大家可以學(xué)習(xí)一下,學(xué)習(xí)完之后肯定會有收獲的,下面讓小編帶大家一起來看看吧。

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供金山網(wǎng)站建設(shè)、金山做網(wǎng)站、金山網(wǎng)站設(shè)計、金山網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、金山企業(yè)網(wǎng)站模板建站服務(wù),十多年金山做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。

功能需求

        最近項目中有這么一個功能,用戶登錄系統(tǒng)后,需要給 用戶 頒發(fā)一個 token ,后續(xù)訪問系統(tǒng)的請求都需要帶上這個 token ,如果請求沒有帶上這個 token 或者 token 過期了,那么禁止訪問系統(tǒng)。如果用戶一直訪問系統(tǒng),那么還需要自動延長 token 的過期時間。

功能分析

1、token 的生成

使用現(xiàn)在比較流行的 jwt 來生成。

2、token 的自動延長

要實現(xiàn) token 的自動延長,系統(tǒng)給用戶 頒發(fā) 一個 token 無法實現(xiàn),那么通過變通一個,給用戶生成 2個 token ,一個用于 api 訪問的 token ,一個 用于在 token 過期的時候 用來 刷新 的 refreshToken。并且 refreshToken 的 生命周期要比 token 的生命周期長。

3、系統(tǒng)資源的保護(hù)

可以使用Spring Security 來保護(hù)系統(tǒng)的各種資源。

4、用戶如何傳遞 token

系統(tǒng)中 tokenrefreshToken 的傳遞一律放在請求頭。

實現(xiàn)思路

1、生成 token 和 refreshToken

用戶登錄系統(tǒng)的時候,后臺給用戶生成 tokenrefreshToken 并放在響應(yīng)頭中返回

2、系統(tǒng) 判斷 token 是否合法

  • token 未失效的時的處理
  • token 失效 ,如何使用refreshToken來生成新的 token

SpringSecurity Jwt Token如何實現(xiàn)自動刷新

核心代碼如下

1、過濾器代碼,token判斷和再次生成

package com.huan.study.security.token;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.huan.study.security.configuration.TokenProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huan 2020-06-07 - 14:34
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class TokenAuthenticateFilter extends OncePerRequestFilter {

  private final TokenProperties tokenProperties;
  private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    // 獲取 認(rèn)證頭
    String authorizationHeader = request.getHeader(tokenProperties.getAuthorizationHeaderName());
    if (!checkIsTokenAuthorizationHeader(authorizationHeader)) {
      log.debug("獲取到認(rèn)證頭Authorization的值:[{}]但不是我們系統(tǒng)中登錄后簽發(fā)的。", authorizationHeader);
      filterChain.doFilter(request, response);
      return;
    }
    // 獲取到真實的token
    String realToken = getRealAuthorizationToken(authorizationHeader);
    // 解析 jwt token
    Jws<Claims> jws = JwtUtils.parserAuthenticateToken(realToken, tokenProperties.getSecretKey());
    // token 不合法
    if (null == jws) {
      writeJson(response, "認(rèn)證token不合法");
      return;
    }
    // token 是否過期
    if (JwtUtils.isJwtExpired(jws)) {
      // 處理過期
      handleTokenExpired(response, request, filterChain);
      return;
    }

    // 構(gòu)建認(rèn)證對象
    JwtUtils.buildAuthentication(jws, tokenProperties.getUserId());

    filterChain.doFilter(request, response);
  }

  /**
   * 處理token過期情況
   *
   * @param response
   * @param request
   * @param filterChain
   * @return
   * @throws IOException
   */
  private void handleTokenExpired(HttpServletResponse response, HttpServletRequest request, FilterChain filterChain) throws IOException, ServletException {
    // 獲取刷新 token
    String refreshTokenHeader = request.getHeader(tokenProperties.getRefreshHeaderName());
    // 檢測 refresh-token 是否是我們系統(tǒng)中簽發(fā)的
    if (!checkIsTokenAuthorizationHeader(refreshTokenHeader)) {
      log.debug("獲取到刷新認(rèn)證頭:[{}]的值:[{}]但不是我們系統(tǒng)中登錄后簽發(fā)的。", tokenProperties.getRefreshHeaderName(), refreshTokenHeader);
      writeJson(response, "token過期了,refresh token 不是我們系統(tǒng)簽發(fā)的");
      return;
    }
    // 解析 refresh-token
    Jws<Claims> refreshToken = JwtUtils.parserAuthenticateToken(getRealAuthorizationToken(refreshTokenHeader),
        tokenProperties.getSecretKey());
    // 判斷 refresh-token 是否不合法
    if (null == refreshToken) {
      writeJson(response, "refresh token不合法");
      return;
    }
    // 判斷 refresh-token 是否過期
    if (JwtUtils.isJwtExpired(refreshToken)) {
      writeJson(response, "refresh token 過期了");
      return;
    }
    // 重新簽發(fā) token

    String newToken = JwtUtils.generatorJwtToken(
        refreshToken.getBody().get(tokenProperties.getUserId()),
        tokenProperties.getUserId(),
        tokenProperties.getTokenExpireSecond(),
        tokenProperties.getSecretKey()
    );
    response.addHeader(tokenProperties.getAuthorizationHeaderName(), newToken);

    // 構(gòu)建認(rèn)證對象
    JwtUtils.buildAuthentication(JwtUtils.parserAuthenticateToken(newToken, tokenProperties.getSecretKey()), tokenProperties.getUserId());

    filterChain.doFilter(request, response);
  }

  /**
   * 寫 json 數(shù)據(jù)給前端
   *
   * @param response
   * @throws IOException
   */
  private void writeJson(HttpServletResponse response, String msg) throws IOException {
    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    Map<String, String> params = new HashMap<>(4);
    params.put("msg", msg);
    response.getWriter().print(OBJECT_MAPPER.writeValueAsString(params));
  }

  /**
   * 獲取到真實的 token 串
   *
   * @param authorizationToken
   * @return
   */
  private String getRealAuthorizationToken(String authorizationToken) {
    return StringUtils.substring(authorizationToken, tokenProperties.getTokenHeaderPrefix().length()).trim();
  }

  /**
   * 判斷是否是系統(tǒng)中登錄后簽發(fā)的token
   *
   * @param authorizationHeader
   * @return
   */
  private boolean checkIsTokenAuthorizationHeader(String authorizationHeader) {
    if (StringUtils.isBlank(authorizationHeader)) {
      return false;
    }
    if (!StringUtils.startsWith(authorizationHeader, tokenProperties.getTokenHeaderPrefix())) {
      return false;
    }
    return true;
  }
}

2、jwt 工具類代碼

package com.huan.study.security.token;

import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.DefaultJws;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;

/**
 * jwt 工具類
 *
 * @author huan
 * @date 2020-05-20 - 17:09
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JwtUtils {

  /**
   * 解析 jwt token
   *
   * @param token   需要解析的json
   * @param secretKey 密鑰
   * @return
   */
  public static Jws<Claims> parserAuthenticateToken(String token, String secretKey) {
    try {
      final Jws<Claims> claimsJws = Jwts.parser()
          .setSigningKey(secretKey)
          .parseClaimsJws(token);
      return claimsJws;
    } catch (ExpiredJwtException e) {
      return new DefaultJws<>(null, e.getClaims(), "");
    } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException | IncorrectClaimException e) {
      log.error(e.getMessage(), e);
      return null;
    }
  }

  /**
   * 判斷 jwt 是否過期
   *
   * @param jws
   * @return true:過期 false:沒過期
   */
  public static boolean isJwtExpired(Jws<Claims> jws) {
    return jws.getBody().getExpiration().before(new Date());
  }

  /**
   * 構(gòu)建認(rèn)證過的認(rèn)證對象
   */
  public static Authentication buildAuthentication(Jws<Claims> jws, String userIdFieldName) {
    Object userId = jws.getBody().get(userIdFieldName);
    TestingAuthenticationToken testingAuthenticationToken = new TestingAuthenticationToken(userId, null, new ArrayList<>(0));
    SecurityContextHolder.getContext().setAuthentication(testingAuthenticationToken);
    return SecurityContextHolder.getContext().getAuthentication();
  }

  /**
   * 生成 jwt token
   */
  public static String generatorJwtToken(Object loginUserId, String userIdFieldName, Long expireSecond, String secretKey) {
    Date expireTime = Date.from(LocalDateTime.now().plusSeconds(expireSecond).atZone(ZoneId.systemDefault()).toInstant());
    return Jwts.builder()
        .setHeaderParam("typ", "JWT")
        .setIssuedAt(new Date())
        .setExpiration(expireTime)
        .claim(userIdFieldName, loginUserId)
        .signWith(SignatureAlgorithm.HS256, secretKey)
        .compact();
  }
}

以上就是關(guān)于SpringSecurity Jwt Token如何實現(xiàn)自動刷新的內(nèi)容,如果你們有學(xué)習(xí)到知識或者技能,可以把它分享出去讓更多的人看到。

網(wǎng)站題目:SpringSecurityJwtToken如何實現(xiàn)自動刷新
當(dāng)前地址:http://aaarwkj.com/article12/pcoegc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、網(wǎng)站維護(hù)、微信公眾號、標(biāo)簽優(yōu)化、營銷型網(wǎng)站建設(shè)、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
人妻激情偷乱视91九色| 久久99国产精品成人免费| 亚洲欧美国产另类精品| 97视频在线中文字幕| 极品大胸美女被啪啪的高潮| 日韩欧美亚洲综合久久精品| 成人黄色大片免费看| 亚洲日本韩国在线免费| 天天躁人人躁夜夜躁狠狠躁| 欧美在线日韩一区二区| 国产三级国产精品国产| 一卡二卡精品在线免费| 国产一区中文字幕在线| 中文字幕一区免费视频| 久久亚洲av麻衣北条麻妃| 亚洲日日夜夜噜噜爽爽| 国产交换精品一区二区三区| 成人爱爱免费观看视频| 欧美老熟妇精品一区二区| 青青草原在线影视一区| 日韩人妻精品久久免费| 欧美日韩亚洲国产一区| 欧美精品亚洲二区中文乱码| 亚洲一区二区视频在线播放| 2020中文字字幕在线不卡| 亚洲毛片在线免费播放| 高潮内射一区二区三区| 欧美精品亚洲精品国产| 国产丝袜在线福利观看| 中文字幕在线精品乱码麻豆| 老司机看片午夜久久福利| 韩国电视剧大全免费国语观看| 亚洲国产传媒在线观看| 欧美亚洲午夜一二综合| 国产91高清在线观看| av在线中文字幕乱码| 国产一区二区三区av网站| 91麻豆视频福利视频| 69人妻一区二区三区蜜桃| 深夜福利视频一区二区| 久久国产精品欧美熟妇|