这篇文章主要讲解了“shiro集成jwt怎么禁用session”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“shiro集成jwt怎么禁用session”吧!
我们提供的服务有:成都做网站、网站设计、外贸营销网站建设、微信公众号开发、网站优化、网站认证、康平ssl等。为成百上千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的康平网站制作公司
shiro 集成 jwt 需要禁用 session, 服务器就不用维护用户的状态, 做到无状态调用
org.apache.shiro shiro-spring-boot-web-starter 1.5.3
com.auth0 java-jwt 3.10.3
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(); SetpermissionSet = shiroService.listPermissions(username); permissionSet.add("perm-1"); // 造数据, 假装是从数据库查出来的 permissionSet.add("perm-2"); simpleAuthorizationInfo.setStringPermissions(permissionSet); Set 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()); MapfilterMap = new HashMap<>(); filterMap.put("customFilter", new CustomFilter()); shiroFilterFactoryBean.setFilters(filterMap); Map 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这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!