真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么在Springboot中使用shiro和jwt實(shí)現(xiàn)前后端分離

這篇文章給大家介紹怎么在Spring boot中使用shiro和jwt實(shí)現(xiàn)前后端分離,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

在北京等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營銷,成都外貿(mào)網(wǎng)站建設(shè)公司,北京網(wǎng)站建設(shè)費(fèi)用合理。



  org.apache.shiro
  shiro-spring
  1.4.0


  org.apache.shiro
  shiro-ehcache
  1.4.0




  com.auth0
  java-jwt
  3.4.0



   io.jsonwebtoken
   jjwt
   0.9.0

創(chuàng)建shiro的自定義的Realm

代碼如下:

package com.serverprovider.config.shiro.userRealm;
 
 
import com.spring.common.auto.autoUser.AutoUserModel;
import com.spring.common.auto.autoUser.extend.AutoModelExtend;
import com.serverprovider.config.shiro.jwt.JWTCredentialsMatcher;
import com.serverprovider.config.shiro.jwt.JwtToken;
import com.serverprovider.service.loginService.LoginServiceImpl;
import com.util.redis.RedisUtil;
import com.util.ReturnUtil.SecretKey;
import com.util.encryption.JWTDecodeUtil;
import io.jsonwebtoken.Claims;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
 
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public class UserRealm extends AuthorizingRealm {
 
  private Logger logger = Logger.getLogger(UserRealm.class);
 
 
  @Autowired private LoginServiceImpl loginService;
 
 
  public UserRealm(){
    //這里使用我們自定義的Matcher驗(yàn)證接口
    this.setCredentialsMatcher(new JWTCredentialsMatcher());
  }
 
  /**
   * 必須重寫此方法,不然Shiro會(huì)報(bào)錯(cuò)
   */
  @Override
  public boolean supports(AuthenticationToken token) {
    return token instanceof JwtToken;
  }
 
  /**
   * shiro 身份驗(yàn)證
   * @param token
   * @return boolean
   * @throws AuthenticationException 拋出的異常將有統(tǒng)一的異常處理返回給前端
   *
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {
    /**
     * AuthenticationToken
     * JwtToken重寫了AuthenticationToken接口 并創(chuàng)建了一個(gè)接口token的變量
     *  因?yàn)樵趂ilter我們將token存入了JwtToken的token變量中
     *  所以這里直接getToken()就可以獲取前端傳遞的token值
     */
      String JWTtoken = ((JwtToken) token).getToken();
    /**
     * Claims對象它最終是一個(gè)JSON格式的對象,任何值都可以添加到其中
     * token解密 轉(zhuǎn)換成Claims對象
     */
       Claims claims = JWTDecodeUtil.parseJWT(JWTtoken, SecretKey.JWTKey);
      
    /**
     *  根據(jù)JwtUtil加密方法加入的參數(shù)獲取數(shù)據(jù)
     *  查詢數(shù)據(jù)庫獲得對象
     *  如為空:拋出異常
     *  如驗(yàn)證失敗拋出 AuthorizationException
     */
      String username = claims.getSubject();
      String password = (String) claims.get("password");
      AutoModelExtend principal = loginService.selectLoginModel(username,password);
      return new SimpleAuthenticationInfo(principal, JWTtoken,"userRealm");
  }
 
 
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    SimpleAuthorizationInfo info = null;
    /**
     * PrincipalCollection對象
     * 文檔里面描述:返回從指定的Realm 僅作為Collection 返回的單個(gè)Subject的對象,如果沒有來自該領(lǐng)域的任何對象,則返回空的Collection。
     * 在登錄接口放入權(quán)限注解返回的錯(cuò)誤信息:Subject.login(AuthenticationToken)或SecurityManager啟用'Remember Me'功能后成功自動(dòng)獲取這些標(biāo)識(shí)主體
     * 當(dāng)調(diào)用Subject.login()方法成功后 PrincipalCollection會(huì)自動(dòng)獲得該對象 如沒有認(rèn)證過或認(rèn)證失敗則返回空的Collection并拋出異常
     * getPrimaryPrincipal():返回在應(yīng)用程序范圍內(nèi)使用的主要對象,以唯一標(biāo)識(shí)擁有帳戶。
     */
    Object principal = principals.getPrimaryPrincipal();
    /**
     * 得到身份對象
     * 查詢該用戶的權(quán)限信息
     */
    AutoUserModel user = (AutoUserModel) principal;
    List roleModels = loginService.selectRoleDetails(user.getId());
    try {
    /**
     * 創(chuàng)建一個(gè)Set,來放置用戶擁有的權(quán)限
     * 創(chuàng)建 SimpleAuthorizationInfo, 并將辦好權(quán)限列表的Set放入.
     */
    Set rolesSet = new HashSet();
    for (String role : roleModels) {
      rolesSet.add(role);
    }
    info = new SimpleAuthorizationInfo();
    info.setStringPermissions(rolesSet);  // 放入權(quán)限信息
  }catch (Exception e){
    throw new AuthenticationException("授權(quán)失敗!");
  }
    return info;
  }
}

這個(gè)授權(quán)方法遇到的坑比較少,就是在最終驗(yàn)證的時(shí)候網(wǎng)上很照抄過來的帖子一點(diǎn)都沒有驗(yàn)證就粘貼賦值,在這里嚴(yán)重吐槽。

在使用jwt最為token而取消shiro傳統(tǒng)的session時(shí)候,我們的需要重寫shiro的驗(yàn)證接口   CredentialsMatcher,在 自定義的realm

中我們加入我們重寫的驗(yàn)證方法,在調(diào)用SimpleAuthenticationInfo()方法進(jìn)行驗(yàn)證的時(shí)候,shiro就會(huì)使用重寫的驗(yàn)證接口。

此處為大坑。

貼上代碼如下:

import com.spring.common.auto.autoUser.extend.AutoModelExtend;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
 
 
 
/**
 * CredentialsMatcher
 * 接口由類實(shí)現(xiàn),該類可以確定是否提供了AuthenticationToken憑證與系統(tǒng)中存儲(chǔ)的相應(yīng)帳戶的憑證相匹配。
 * Shiro 加密匹配 重寫匹配方法CredentialsMatcher 使用JWTUtil 匹配方式
 */
public class JWTCredentialsMatcher implements CredentialsMatcher {
 
  private Logger logger = Logger.getLogger(JWTCredentialsMatcher.class);
 
  /**
   * Matcher中直接調(diào)用工具包中的verify方法即可
   */
  @Override
  public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
    String token = (String) ((JwtToken)authenticationToken).getToken();
    AutoModelExtend user = (AutoModelExtend)authenticationInfo.getPrincipals().getPrimaryPrincipal();
    //得到DefaultJwtParser
    Boolean verify = JwtUtil.isVerify(token, user);
    logger.info("JWT密碼效驗(yàn)結(jié)果="+verify);
    return verify;
  }
}

shiro的配置項(xiàng)  ShiroConfiguration代碼如下:

import com.serverprovider.config.shiro.shiroSysFile.JwtFilter;
import com.serverprovider.config.shiro.userRealm.UserRealm;
import org.apache.log4j.Logger;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
 
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import javax.servlet.Filter;
import java.util.*;
 
@Configuration
public class ShiroConfiguration {
 
  private Logger logger = Logger.getLogger(ShiroConfiguration.class);
 
 
 
  @Bean("shiroFilter")
  public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    //攔截器
    Map filterChainDefinitionMap = new LinkedHashMap();
    // 配置不會(huì)被攔截的鏈接 順序判斷
    filterChainDefinitionMap.put("/login/**", "anon");
    // 添加自己的過濾器并且取名為jwt
    Map filterMap = new HashMap();
    filterMap.put("jwt", new JwtFilter());
    shiroFilterFactoryBean.setFilters(filterMap);
    //
        

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部