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

溫馨提示×

溫馨提示×

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

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

如何基于springSecurity的Json Web Token的實現

發布時間:2021-10-12 15:08:14 來源:億速云 閱讀:153 作者:柒染 欄目:大數據

本篇文章給大家分享的是有關如何基于springSecurity的Json Web Token的實現,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

SecurityJwt

一個基于springSecurity的Json Web Token的實現

GitHub地址


提要

一、SpringSecurity

  • Spring Security,一種基于 Spring AOPServlet 過濾器的安全框架。它提供全面的安全性解決方案,同時在 Web 請求級和方法調用級處理身份確認和授權。。

  • 來自Spring全家桶系列,與SpringBoot無縫銜接。為應用系統提供聲明式的安全訪問控制功能,減少了為企業系統安全控制編寫大量重復代碼的工作。

二、JSON Web Token

  • JSON Web Token(JWT)準確來說是一個規范。實際上就是一個字符串,它由三部分組成——頭部Header、載荷playload與簽名signature)。

  • 頭部Header)用于描述關于該JWT的最基本的信息,即該JWT本身的信息聲明,如簽名所用算法。

  • 載荷playload)是存放有效信息的地方。其中信息又分為三個部分——聲明部分公共部分(subject)私有部分(claim)

  • 簽證signature)需要base64加密后的headerbase64加密后的payload使用.連接組成的字符串,然后通過header中聲明的加密方式進行加鹽secret組合加密構成(注意secret是保存在服務器端的)。

  • 在分布式中直接根據token取出保存的用戶信息,以及對token可用性校驗,單點登錄更為簡單。

  • 如何基于springSecurity的Json Web Token的實現

三、開發環境介紹

  • Java版本:1.8

  • 構建工具:Gradle(目前國內主流構建工具依然是Maven,但是筆者用過Gradle之后就不想再用Maven了,因為Gradle是真的方便很多。其倉庫結構向下兼容Maven,也就是說可以使用任何Maven倉庫。

build.gradle文件:

plugins {
    id 'org.springframework.boot' version '2.2.0.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

group = 'org.zuoyu'
version = '1.0.0'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
//    這里使用的是阿里巴巴的Maven倉庫
    maven {
        url 'http://maven.aliyun.com/nexus/content/groups/public/'
    }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
//    jwt依賴
    runtime('io.jsonwebtoken:jjwt-jackson:0.10.7')
    runtime('io.jsonwebtoken:jjwt-impl:0.10.7')
    compile('io.jsonwebtoken:jjwt-api:0.10.7')
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    testImplementation 'org.springframework.security:spring-security-test'
}

test {
    useJUnitPlatform()
}

四、源碼說明

在這里只分析關鍵代碼(其中的JwtConstants.java是我自定義的final變量類)
備注:security的配置文件中,將session管理器關閉,沒有必要使用session
1. JwtTokenUtils.java(JWT的工具類)
/**
   * 構建JWT
   *
   * @param subject - 實體
   * @param authorities - 權限
   * @param expiration - 保留時間
   * @return - token
   */
  private static String createJwt(String subject,
      String authorities, long expiration) {
    long nowMillis = System.currentTimeMillis();
    return Jwts.builder()
        .setId(JwtConstants.createTokenId())
        .signWith(SECRET_KEY, SignatureAlgorithm.HS256)
        .setIssuer(JwtConstants.JWT_ISSUER)
        .setSubject(subject)
        .claim(JwtConstants.ROLE_CLAIMS, authorities)
        .setIssuedAt(new Date(nowMillis))
        .setNotBefore(new Date(nowMillis))
        .setExpiration(new Date(nowMillis + expiration * 1000L))
        .compact();
  }

在這里我們使用官方依賴包中的Jwts.builder()方法,創建一個token,其中——

  • signWith就是設置私密鑰與加密方式,SECRET_KEY為私密鑰,SignatureAlgorithm.HS256為加密方式。

  • setSubject為設置公共部分,該部分在客戶端可解密。

  • claim為設置私有部分,其參數為keyvalue形式。

  • setIssuedAttoken的簽發時間。

  • setNotBeforetoken的生效時間。

  • setExpirationtoken的失效時間。

解析token

/**
   * 解析token
   *
   * @param token -
   * @return - Claims
   */
  private static Claims parseJwt(String token) {
    return Jwts.parser()
        .setSigningKey(SECRET_KEY)
        .parseClaimsJws(token)
        .getBody();
  }

在這里重點在與setSigningKey,傳入我們在創建時候的私密鑰SECRET_KEY

還有幾個與security方便交互的方法:

 /**
   * 根據賬戶構建token
   *
   * @param user - 賬戶
   * @return -
   */
  public static String createToken(User user, boolean isRememberMe) {
    long expiration =
        isRememberMe ? JwtConstants.EXPIRATION_REMEMBER : JwtConstants.EXPIRATION;
    String spacer = ",";
    List<string> authorities = Arrays.stream(user.getRoles().split(spacer))
        .map(role -&gt; "ROLE_" + role)
        .collect(Collectors.toList());
    return createJwt(JsonUtil.beanToJsonString(user), JsonUtil.objectToJsonString(authorities),
        expiration);
  }



  /**
   * 獲取用戶
   *
   * @param token - token
   * @return - User
   */
  public static User getUserByToken(String token) {
    String subject = parseJwt(token).getSubject();
    return JsonUtil.jsonStringToBean(subject, User.class);
  }


/**
   * 獲取用戶的權限
   * @param token - token
   * @return - 權限列表
   */
  public static Collection<!--? extends GrantedAuthority--> getAuthoritiesByToken(String token) {
    String roles = parseJwt(token).get(JwtConstants.ROLE_CLAIMS).toString();
    return JsonUtil.jsonStringToCollection(roles, SimpleGrantedAuthority.class);
  }
2. AuthenticationSuccessHandlerImpl.java(Security登錄成功后的執行行為)
/**
 * 登錄成功的實現.
 *
 * @author zuoyu
 **/
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
      Authentication authentication) throws IOException {
    String rememberMe = request.getParameter(JwtConstants.USER_LOGIN_REMEMBER_ME);
    boolean isRememberMe = Boolean.parseBoolean(rememberMe);
    User principal = (User) authentication.getPrincipal();
    String token = JwtTokenUtils.createToken(principal, isRememberMe);
    response.setContentType("application/json;charset=utf-8");
    response.setHeader(JwtConstants.TOKEN_HEADER, token);
    response.setStatus(HttpServletResponse.SC_OK);
    PrintWriter responseWriter = response.getWriter();
    responseWriter.write("{\"message\":\"登錄成功\"}");
    responseWriter.flush();
    responseWriter.close();
  }


}

這段代碼主要思路是——登錄成功后,在authentication中獲取已經認證成功的用戶信息(user),然后將該user轉換為token并返回給客戶端。其中的isRememberMe是根據是否為true給予token不同的有效時間(查看完整源代碼)。

3. JwtAuthorizationFilter.java(自定義基于JWT認證的過濾器)
/**
 * JWT的權限過濾器.
 *
 * @author zuoyu
 * @program jwt
 * @create 2019-10-17 16:26
 **/
@Slf4j
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

  public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
    super(authenticationManager);
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    String token = request.getHeader(JwtConstants.TOKEN_HEADER);
    if (StringUtils.isEmpty(token)) {
      chain.doFilter(request, response);
      return;
    }
    User user = JwtTokenUtils.getUserByToken(token);
    Collection<!--? extends GrantedAuthority--> authorities = JwtTokenUtils.getAuthoritiesByToken(token);
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
        user, null, authorities);
    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
    super.doFilterInternal(request, response, chain);
  }
}

這段代碼的從請求中獲取token,并將從token中解析出用戶信息(user)和權限信息(authorities)。并根據用戶信息(user)和權限信息(authorities)創建屬于security框架的權限身份(authentication),將其存入當前的security環境。

五、使用方法

  • 項目啟動后自動建表(JPA)
  • 注冊(登錄)的賬戶名稱字段為userName
  • 注冊(登錄)的賬戶密碼字段為passWord
  • 登錄時的“記住我”字段為rememberMe

如何使用——

  1. 登錄之后,在響應Response的頭Headers里有字段Authorization,該值就是Token

  2. 后續的訪問需在Request的頭Headers內攜帶字段Authorization和其值,以此來表示身份。

  3. rememberMe默認時效為一小時,為true時時效7天,設置路徑在org.zuoyu.security.jwt.constants.JwtConstants.java

  4. 測試路徑查看org.zuoyu.security.jwt.controller.AuthController.java類。

以上就是如何基于springSecurity的Json Web Token的實現,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

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

AI

怀柔区| 新乡县| 大埔县| 沂水县| 子长县| 青铜峡市| 张家港市| 黑河市| 泸水县| 雷州市| 繁峙县| 仁布县| 张家港市| 石泉县| 沈阳市| 扶绥县| 凌源市| 淅川县| 曲麻莱县| 大连市| 邵武市| 桐梓县| 凉山| 西丰县| 上杭县| 蒙城县| 淮南市| 古田县| 梁山县| 蒙阴县| 平顶山市| 浏阳市| 辽阳县| 都安| 大足县| 含山县| 云林县| 桑植县| 普洱| 弋阳县| 澄城县|