您好,登錄后才能下訂單哦!
這篇文章主要講解了“shiro集成jwt怎么禁用session”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“shiro集成jwt怎么禁用session”吧!
shiro 集成 jwt 需要禁用 session, 服務器就不用維護用戶的狀態, 做到無狀態調用
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency>
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency>
1. 定義一個 JwtToken, 用來封裝 username 和 jsonWebToken
package com.codingos.shirojwt.shiro; import org.apache.shiro.authc.AuthenticationToken; public class JwtToken implements AuthenticationToken{ private static final long serialVersionUID = 5467074955086481181L; private String username; private String jsonWebToken; public JwtToken(String username, String jsonWebToken) { this.username = username; this.jsonWebToken = jsonWebToken; } @Override public Object getPrincipal() { return username; } @Override public Object getCredentials() { return jsonWebToken; } }
2. 自定義一個 Filter 用來過濾所有請求, 交給realm進行驗證
package com.codingos.shirojwt.shiro; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.web.filter.AccessControlFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.DecodedJWT; import com.codingos.shirojwt.common.CommonUtils; public class CustomFilter extends AccessControlFilter{ private final Logger logger = LoggerFactory.getLogger(getClass()); @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return false; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { if(logger.isDebugEnabled()) { logger.debug("訪問的URI: {}", ((HttpServletRequest) request).getRequestURI()); } String jsonWebToken = CommonUtils.getJsonWebToken((HttpServletRequest) request); String username = ""; if (StringUtils.isBlank(jsonWebToken)) { jsonWebToken = ""; } else { // 解碼 jwt DecodedJWT decodeJwt = JWT.decode(jsonWebToken); username = decodeJwt.getClaim("username").asString(); } JwtToken token = new JwtToken(username, jsonWebToken); try { // 交給自定義realm進行jwt驗證和對應角色,權限的查詢 getSubject(request, response).login(token); } catch (AuthenticationException e) { request.setAttribute("msg", "認證失敗"); // 轉發給指定的 controller, 進行統一異常處理 ((HttpServletRequest)request).getRequestDispatcher("/exception").forward(request, response); return false; } return true; } }
3. 創建自定義realm, 用來驗證 jwt , role, permission
package com.codingos.shirojwt.shiro; import java.util.Set; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import com.codingos.shirojwt.constant.Constant; import com.codingos.shirojwt.service.ShiroService; public class CustomRealm extends AuthorizingRealm { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ShiroService shiroService; public CustomRealm() { } @Override public boolean supports(AuthenticationToken token) { // 僅支持 JwtToken return token instanceof JwtToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 獲取用戶名, 用戶唯一標識 String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); Set<String> permissionSet = shiroService.listPermissions(username); permissionSet.add("perm-1"); // 造數據, 假裝是從數據庫查出來的 permissionSet.add("perm-2"); simpleAuthorizationInfo.setStringPermissions(permissionSet); Set<String> roleSet = shiroService.listRoles(username); roleSet.add("role-1"); // 造數據, 假裝是從數據庫查出來的 roleSet.add("role-2"); simpleAuthorizationInfo.setRoles(roleSet); return simpleAuthorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); String jsonWebToken = (String) token.getCredentials(); Algorithm algorithm = Algorithm.HMAC256(Constant.JWT_SECRET); JWTVerifier verifier = JWT.require(algorithm).build(); try { verifier.verify(jsonWebToken); if(logger.isDebugEnabled()) { logger.debug("********************* 驗證通過 ***********************"); } } catch (JWTVerificationException e) { if(logger.isDebugEnabled()) { logger.debug("********************* 驗證不通過 **********************"); } jsonWebToken = "invalid jwt"; } SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, jsonWebToken, getName()); return simpleAuthenticationInfo; } }
4. 定義一個 WebSubjectFactory, 用來禁用 session
package com.codingos.shirojwt.shiro; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.SubjectContext; import org.apache.shiro.web.mgt.DefaultWebSubjectFactory; public class CustomWebSubjectFactory extends DefaultWebSubjectFactory { @Override public Subject createSubject(SubjectContext context) { // 禁用session context.setSessionCreationEnabled(false); return super.createSubject(context); } }
5. 定義一個 shiro 的配置類
package com.codingos.shirojwt.shiro; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; import org.apache.shiro.mgt.DefaultSubjectDAO; import org.apache.shiro.realm.Realm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.mgt.DefaultWebSubjectFactory; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class ShiroConfig { @Bean public Realm realm() { return new CustomRealm(); } @Bean public DefaultWebSubjectFactory subjectFactory() { return new CustomWebSubjectFactory(); } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm()); securityManager.setSubjectFactory(subjectFactory()); DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator(); // 禁用 session 存儲 sessionStorageEvaluator.setSessionStorageEnabled(false); subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator); securityManager.setSubjectDAO(subjectDAO); // 禁用 rememberMe securityManager.setRememberMeManager(null); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); Map<String, Filter> filterMap = new HashMap<>(); filterMap.put("customFilter", new CustomFilter()); shiroFilterFactoryBean.setFilters(filterMap); Map<String, String> filterChainDefinitionMap = new HashMap<>(); filterChainDefinitionMap.put("/tologin", "anon"); filterChainDefinitionMap.put("/exception", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/error", "anon"); filterChainDefinitionMap.put("/todenied", "anon"); filterChainDefinitionMap.put("/**", "customFilter"); // filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); shiroFilterFactoryBean.setLoginUrl("/tologin"); shiroFilterFactoryBean.setSuccessUrl("/indexpage"); shiroFilterFactoryBean.setUnauthorizedUrl("/todenied"); return shiroFilterFactoryBean; } }
在shiro禁用session后, 如果再使用 shiro 的內置過濾器 authc, 就會報錯, 所以就不用再用 authc, 使用自定義的那個Filter就行
感謝各位的閱讀,以上就是“shiro集成jwt怎么禁用session”的內容了,經過本文的學習后,相信大家對shiro集成jwt怎么禁用session這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。