RBAC项目中用到的Shiro、Jwt相关配置以及工具类
Maven 依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 <!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> <!--JWT--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.3.0</version> </dependency>
Jwt相关 JWTUtils.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 package com.marlowe.rbac.utils;import com.auth0.jwt.JWT;import com.auth0.jwt.JWTVerifier;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.exceptions.JWTDecodeException;import com.auth0.jwt.interfaces.DecodedJWT;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.io.UnsupportedEncodingException;import java.util.Date;@Component @ConfigurationProperties(prefix = "self.jwt") public class JWTUtils { private String secret; private long expire; private String header; public boolean verify (String token, String username, String secret) { try { Algorithm algorithm = Algorithm.HMAC256(secret); JWTVerifier verifier = JWT.require(algorithm) .withClaim("username" , username) .build(); verifier.verify(token); return true ; } catch (Exception exception) { return false ; } } public String getUsername (String token) { try { DecodedJWT jwt = JWT.decode(token); return jwt.getClaim("username" ).asString(); } catch (JWTDecodeException e) { return null ; } } public String sign (String username, String secret) { try { Date date = new Date(System.currentTimeMillis() + this .expire); Algorithm algorithm = Algorithm.HMAC256(secret); return JWT.create() .withClaim("username" , username) .withExpiresAt(date) .sign(algorithm); } catch (UnsupportedEncodingException e) { return null ; } } public boolean isExpire (String token) { DecodedJWT jwt = JWT.decode(token); return System.currentTimeMillis() > jwt.getExpiresAt().getTime(); } public String getSecret () { return secret; } public long getExpire () { return expire; } public String getHeader () { return header; } public void setSecret (String secret) { this .secret = secret; } public void setExpire (long expire) { this .expire = expire; } public void setHeader (String header) { this .header = header; } }
JWTToken.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.marlowe.rbac.config.shiro.jwt;import org.apache.shiro.authc.AuthenticationToken;public class JWTToken implements AuthenticationToken { private String token; public JWTToken () { } public JWTToken (String token) { this .token = token; } @Override public Object getPrincipal () { return token; } @Override public Object getCredentials () { return token; } }
JWTFilter.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 package com.marlowe.rbac.config.shiro.jwt;import com.auth0.jwt.exceptions.JWTDecodeException;import com.fasterxml.jackson.databind.ObjectMapper;import com.marlowe.rbac.commons.result.Result;import com.marlowe.rbac.utils.JWTUtils;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;import org.apache.shiro.web.util.WebUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.HashMap;@Component public class JWTFilter extends BasicHttpAuthenticationFilter { private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired private JWTUtils jwtUtils; @Override protected boolean onAccessDenied (ServletRequest request, ServletResponse response) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String token = httpServletRequest.getHeader(this .jwtUtils.getHeader()); if (null == token || "" .equals(token)) { this .responseTokenError(response, "请求头异常或token为空值!" ); return false ; } JWTToken jwtToken = new JWTToken(token); try { SecurityUtils.getSubject().login(jwtToken); } catch (AuthenticationException e) { responseTokenError(response, e.getMessage()); return false ; } catch (JWTDecodeException e) { responseTokenError(response, e.getCause().getMessage()); return false ; } return true ; } @Override protected boolean preHandle (ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; httpServletResponse.setHeader("Access-control-Allow-Origin" , httpServletRequest.getHeader("Origin" )); httpServletResponse.setHeader("Access-Control-Allow-Methods" , "GET,POST,OPTIONS,PUT,DELETE" ); httpServletResponse.setHeader("Access-Control-Allow-Headers" , httpServletRequest.getHeader("Access-Control-Request-Headers" )); if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { httpServletResponse.setStatus(HttpStatus.OK.value()); return false ; } return super .preHandle(request, response); } private void responseTokenError (ServletResponse response, String msg) { HttpServletResponse httpServletResponse = WebUtils.toHttp(response); httpServletResponse.setStatus(HttpStatus.OK.value()); httpServletResponse.setCharacterEncoding("UTF-8" ); httpServletResponse.setContentType("application/json; charset=utf-8" ); try { PrintWriter out = httpServletResponse.getWriter(); HashMap<String, Object> errorData = new HashMap<>(); errorData.put("errorCode" , "-1" ); errorData.put("errorMsg" , msg); Result result = Result.ok(errorData); String data = this .objectMapper.writeValueAsString(result); out.append(data); } catch (IOException e) { e.printStackTrace(); System.out.println(e.getMessage()); } } }
Shiro相关 UserRealm.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 package com.marlowe.rbac.config.shiro.realms;import cn.hutool.core.collection.CollectionUtil;import com.auth0.jwt.exceptions.JWTDecodeException;import com.marlowe.rbac.config.shiro.jwt.JWTToken;import com.marlowe.rbac.entity.Permission;import com.marlowe.rbac.entity.User;import com.marlowe.rbac.service.IRoleService;import com.marlowe.rbac.service.IUserService;import com.marlowe.rbac.utils.JWTUtils;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.apache.shiro.util.ByteSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.List;@Component public class UserRealm extends AuthorizingRealm { @Autowired private IUserService userService; @Autowired private IRoleService roleService; @Autowired private JWTUtils jwtUtils; @Override public boolean supports (AuthenticationToken token) { return token instanceof JWTToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principals) { User user = (User) principals.getPrimaryPrincipal(); System.out.println("调用授权验证:" + user.getUsername()); User realUser = userService.findRolesByUserName(user.getUsername()); if (!CollectionUtil.isEmpty(realUser.getRoles())) { SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); System.out.println(realUser.getRoles()+"-------------------------" ); realUser.getRoles().forEach(role -> { simpleAuthorizationInfo.addRole(role.getName()); System.out.println(role.getName()+"================================" ); List<Permission> permissions = roleService.findPermissionsByRoleId(role.getId()); if (!CollectionUtil.isEmpty(permissions)) { permissions.forEach(permission -> { simpleAuthorizationInfo.addStringPermission(permission.getName()); System.out.println(permission.getName()+"==============AAAAAAAAAA==================" ); }); } }); return simpleAuthorizationInfo; } return null ; } @Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken auth) throws AuthenticationException { String token = (String) auth.getPrincipal(); String username; try { username = this .jwtUtils.getUsername(token); if (username == null || !this .jwtUtils.verify(token, username, this .jwtUtils.getSecret())) { if (this .jwtUtils.isExpire(token)) { throw new ExpiredCredentialsException("token过期,请重新登入!" ); } throw new IncorrectCredentialsException("token值异常(2)!!!" ); } } catch (JWTDecodeException | IllegalArgumentException e) { e.printStackTrace(); throw new IncorrectCredentialsException("token值异常(1)!!!!" ); } catch (AuthenticationException e) { e.printStackTrace(); throw new IncorrectCredentialsException(e.getMessage()); } User user = this .userService.findUserByUsername(username); if (user == null ) { throw new UnknownAccountException("账号不存在!" ); } return new SimpleAuthenticationInfo(user, token, this .getName()); } }
ShiroConfig.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 package com.marlowe.rbac.config.shiro;import com.marlowe.rbac.config.shiro.jwt.JWTFilter;import com.marlowe.rbac.config.shiro.realms.UserRealm;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;import org.apache.shiro.mgt.DefaultSubjectDAO;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;@Configuration public class ShiroConfig { @Bean public DefaultSecurityManager securityManager (UserRealm userRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm); DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator(); defaultSessionStorageEvaluator.setSessionStorageEnabled(false ); subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator); securityManager.setSubjectDAO(subjectDAO); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager, JWTFilter jwtFilter) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); Map<String, Filter> newFilters = new HashMap<>(); newFilters.put("jwt" , jwtFilter); shiroFilterFactoryBean.setFilters(newFilters); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> map = new LinkedHashMap<>(); map.put("/login" , "anon" ); map.put("/register" , "anon" ); map.put("/swagger/**" , "anon" ); map.put("/v2/api-docs" , "anon" ); map.put("/swagger-ui.html" , "anon" ); map.put("/swagger-resources/**" , "anon" ); map.put("/webjars/**" , "anon" ); map.put("/favicon.ico" , "anon" ); map.put("/captcha.jpg" , "anon" ); map.put("/csrf" , "anon" ); map.put("/**" , "jwt" ); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } @Bean public FilterRegistrationBean<Filter> registration (JWTFilter jwtFilter) { FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(jwtFilter); registration.setEnabled(false ); return registration; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor (@Qualifier("securityManager") SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } }