亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

怎么在Spring-boot中利用Shrio實現JWT驗證

發布時間:2021-05-19 15:37:41 來源:億速云 閱讀:188 作者:Leah 欄目:編程語言

今天就跟大家聊聊有關怎么在Spring-boot中利用Shrio實現JWT驗證,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

pom.mx引入相關jar包

 <!-- shiro 權限管理 -->
  <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>${shiro.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>${shiro.version}</version>
  </dependency>
 <!-- JWT -->
   <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
  </dependency>

Shrio 的相關配置

劃重點!!自定義了一個Filter

filterMap.put("JWTFilter", new JWTFilter());
@Configuration
public class ShiroConfig {
  @Bean
  public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 添加自己的過濾器并且取名為JWTFilter
    Map<String, Filter> filterMap = new HashMap<>();
    filterMap.put("JWTFilter", new JWTFilter());
    shiroFilterFactoryBean.setFilters(filterMap);
    /*
     * 自定義url規則
     * http://shiro.apache.org/web.html#urls-
     */
    Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
    filterChainDefinitionMap.put("/**", "JWTFilter");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  }


  /**
   * securityManager 不用直接注入shiroDBRealm,可能會導致事務失效
   * 解決方法見 handleContextRefresh
   * http://www.debugrun.com/a/NKS9EJQ.html
   */
  @Bean("securityManager")
  public DefaultWebSecurityManager securityManager(TokenRealm tokenRealm) {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    manager.setRealm(tokenRealm);
    /*
     * 關閉shiro自帶的session,詳情見文檔
     * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
     */
    DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
    DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
    defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
    subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
    manager.setSubjectDAO(subjectDAO);
    return manager;
  }

  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  @Bean(name = "TokenRealm")
  @DependsOn("lifecycleBeanPostProcessor")
  public TokenRealm tokenRealm() {
    return new TokenRealm();
  }

  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    // 強制使用cglib,防止重復代理和可能引起代理出錯的問題
    // https://zhuanlan.zhihu.com/p/29161098
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
  }

  @Bean
  public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return new AuthorizationAttributeSourceAdvisor();
  }
}

自定義Shrio filter

執行順序:preHandle -> doFilterInternal -> executeLogin -> onLoginSuccess

主要判斷是不是登錄請求的是 doFilterInternal

public class JWTFilter extends BasicHttpAuthenticationFilter {
  /**
   * 自定義執行登錄的方法
   */
  @Override
  protected boolean executeLogin(ServletRequest request, ServletResponse response) throws IOException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    UsernamePasswordToken usernamePasswordToken = JSON.parseObject(httpServletRequest.getInputStream(), UsernamePasswordToken.class);
    // 提交給realm進行登入,如果錯誤他會拋出異常并被捕獲
    Subject subject = this.getSubject(request, response);
    subject.login(usernamePasswordToken);
    return this.onLoginSuccess(usernamePasswordToken, subject, request, response);
    //錯誤拋出異常
  }

  /**
   * 最先執行的方法
   */
  @Override
  protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
    return super.preHandle(request, response);
  }

  /**
   * 登錄成功后登錄的操作
   * 加上jwt 的header
   */
  @Override
  protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) {
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    String jwtToken = Jwts.builder()
        .setId(token.getPrincipal().toString())
        .setExpiration(DateTime.now().plusMinutes(30).toDate())
        .signWith(SignatureAlgorithm.HS256, JWTCost.signatureKey)
        .compact();
    httpServletResponse.addHeader(AUTHORIZATION_HEADER, jwtToken);
    return true;
  }

  /**
   * 登錄以及校驗的主要流程
   * 判斷是否是登錄,或者是登陸后普通的一次請求
   */
  @Override
  public void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
    HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
    String servletPath = httpServletRequest.getServletPath();
    if (StringUtils.equals(servletPath, "/login")) {
      //執行登錄
      this.executeLogin(servletRequest, servletResponse);
    } else {
      String authenticationHeader = httpServletRequest.getHeader(AUTHORIZATION_HEADER);
      if (StringUtils.isNotEmpty(authenticationHeader)) {

        Claims body = Jwts.parser()
            .setSigningKey(JWTCost.signatureKey)
            .parseClaimsJws(authenticationHeader)
            .getBody();
        if (body != null) {
          //更新token
          body.setExpiration(DateTime.now().plusMinutes(30).toDate());
          String updateToken = Jwts.builder().setClaims(body).compact();
          httpServletResponse.addHeader(AUTHORIZATION_HEADER, updateToken);

          //添加用戶憑證
          PrincipalCollection principals = new SimplePrincipalCollection(body.getId(), JWTCost.UserNamePasswordRealm);//拼裝shiro用戶信息
          WebSubject.Builder builder = new WebSubject.Builder(servletRequest, servletResponse);
          builder.principals(principals);
          builder.authenticated(true);
          builder.sessionCreationEnabled(false);
          WebSubject subject = builder.buildWebSubject();
          //塞入容器,統一調用
          ThreadContext.bind(subject);
          filterChain.doFilter(httpServletRequest, httpServletResponse);
        }
      } else {
        httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
      }
    }
  }
}

登錄失敗處理

處理Shrio異常

@RestControllerAdvice
public class GlobalControllerExceptionHandler {
  @ExceptionHandler(value = Exception.class)
  public Object allExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    String message = exception.getCause().getMessage();
    LogUtil.error(message);
    return new ResultInfo(exception.getClass().getName(), message);
  }

  /*=========== Shiro 異常攔截==============*/

  @ExceptionHandler(value = IncorrectCredentialsException.class)
  public String IncorrectCredentialsException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "IncorrectCredentialsException";
  }

  @ExceptionHandler(value = UnknownAccountException.class)
  public String UnknownAccountException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "UnknownAccountException";
  }

  @ExceptionHandler(value = LockedAccountException.class)
  public String LockedAccountException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "LockedAccountException";
  }

  @ExceptionHandler(value = ExcessiveAttemptsException.class)
  public String ExcessiveAttemptsException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "ExcessiveAttemptsException";
  }

  @ExceptionHandler(value = AuthenticationException.class)
  public String AuthenticationException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "AuthenticationException";
  }

  @ExceptionHandler(value = UnauthorizedException.class)
  public String UnauthorizedException(HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(HttpStatus.FORBIDDEN.value());
    return "UnauthorizedException";
  }
}

處理JWT異常

這是個坑,因為是在filter內發生的異常,@ExceptionHandler是截獲不到的。

/**
 * 截獲spring boot Error頁面
 */
@RestController
public class GlobalExceptionHandler implements ErrorController {
  @Override
  public String getErrorPath() {
    return "/error";
  }

  @RequestMapping(value = "/error")
  public Object error(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 錯誤處理邏輯
    Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
    Throwable cause = exception.getCause();
    if (cause instanceof ExpiredJwtException) {
      response.setStatus(HttpStatus.GATEWAY_TIMEOUT.value());
      return new ResultInfo("ExpiredJwtException", cause.getMessage());
    }
    if (cause instanceof MalformedJwtException) {
      response.setStatus(HttpStatus.FORBIDDEN.value());
      return new ResultInfo("MalformedJwtException", cause.getMessage());
    }
    return new ResultInfo(cause.getCause().getMessage(), cause.getMessage());
  }
}

springboot是什么

springboot一種全新的編程規范,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程,SpringBoot也是一個服務于框架的框架,服務范圍是簡化配置文件。

看完上述內容,你們對怎么在Spring-boot中利用Shrio實現JWT驗證有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

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

AI

壶关县| 龙川县| 平原县| 内丘县| 德州市| 英德市| 那曲县| 曲沃县| 游戏| 朝阳区| 内丘县| 赫章县| 宜黄县| 开原市| 察雅县| 巴塘县| 双辽市| 锡林浩特市| 阳东县| 台北市| 万年县| 棋牌| 三门县| 牙克石市| 卢龙县| 株洲市| 曲水县| 泽普县| 大埔区| 修水县| 依兰县| 堆龙德庆县| 武平县| 曲阜市| 新安县| 行唐县| 云霄县| 双城市| 镇平县| 台湾省| 东阳市|