Skip to content

Commit 55f76bf

Browse files
committed
添加Shiro自带拦截器配置规则注释,代码规范调整
1 parent c634f5c commit 55f76bf

File tree

5 files changed

+65
-47
lines changed

5 files changed

+65
-47
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Token的自动刷新也是在Token失效时返回新的Token在Header信息的Au
126126
6. 感谢yaxx的Vuejs之axios获取Http响应头:[https://segmentfault.com/a/1190000009125333](https://segmentfault.com/a/1190000009125333)
127127
7. 感谢Twilight的解决使用jwt刷新token带来的问题:[https://segmentfault.com/a/1190000013151506](https://segmentfault.com/a/1190000013151506)
128128
8. 感谢chuhx的shiro拦截器,返回json数据:[https://blog.csdn.net/chuhx/article/details/51148877](https://blog.csdn.net/chuhx/article/details/51148877)
129+
9. 感谢yidao620c的Shiro自带拦截器配置规则:[https://github.com/yidao620c/SpringBootBucket/tree/master/springboot-jwt](https://github.com/yidao620c/SpringBootBucket/tree/master/springboot-jwt)
129130

130131
#### 参与贡献
131132

src/main/java/com/wang/config/shiro/ShiroConfig.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,41 @@ public class ShiroConfig {
3636
*/
3737
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
3838
@Bean("securityManager")
39-
public DefaultWebSecurityManager getManager(UserRealm userRealm) {
40-
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
39+
public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm) {
40+
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
4141
// 使用自定义Realm
42-
manager.setRealm(userRealm);
42+
defaultWebSecurityManager.setRealm(userRealm);
4343
// 关闭Shiro自带的session
4444
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
4545
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
4646
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
4747
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
48-
manager.setSubjectDAO(subjectDAO);
48+
defaultWebSecurityManager.setSubjectDAO(subjectDAO);
4949
// 设置自定义Cache缓存
50-
manager.setCacheManager(new CustomCacheManager());
51-
return manager;
50+
defaultWebSecurityManager.setCacheManager(new CustomCacheManager());
51+
return defaultWebSecurityManager;
5252
}
5353

5454
/**
5555
* 添加自己的过滤器,自定义url规则
56+
* Shiro自带拦截器配置规则
57+
* rest:比如/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等
58+
* port:比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数
59+
* perms:比如/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法
60+
* roles:比如/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,比如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。//要实现or的效果看http://zgzty.blog.163.com/blog/static/83831226201302983358670/
61+
* anon:比如/admins/**=anon 没有参数,表示可以匿名使用
62+
* authc:比如/admins/user/**=authc表示需要认证才能使用,没有参数
63+
* authcBasic:比如/admins/user/**=authcBasic没有参数表示httpBasic认证
64+
* ssl:比如/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
65+
* user:比如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查
5666
* 详情见文档 http://shiro.apache.org/web.html#urls-
5767
* @param securityManager
5868
* @return org.apache.shiro.spring.web.ShiroFilterFactoryBean
5969
* @author Wang926454
6070
* @date 2018/8/31 10:57
6171
*/
6272
@Bean("shiroFilter")
63-
public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
73+
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
6474
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
6575
// 添加自己的过滤器取名为jwt
6676
Map<String, Filter> filterMap = new HashMap<>(16);
@@ -69,6 +79,14 @@ public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager)
6979
factoryBean.setSecurityManager(securityManager);
7080
// 自定义url规则使用LinkedHashMap有序Map
7181
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(16);
82+
// Swagger接口文档
83+
// filterChainDefinitionMap.put("/v2/api-docs", "anon");
84+
// filterChainDefinitionMap.put("/webjars/**", "anon");
85+
// filterChainDefinitionMap.put("/swagger-resources/**", "anon");
86+
// filterChainDefinitionMap.put("/swagger-ui.html", "anon");
87+
// filterChainDefinitionMap.put("/doc.html", "anon");
88+
// 公开接口
89+
// filterChainDefinitionMap.put("/api/**", "anon");
7290
// 所有请求通过我们自己的JWTFilter
7391
filterChainDefinitionMap.put("/**", "jwt");
7492
factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

src/main/java/com/wang/config/shiro/UserRealm.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,17 @@ public UserRealm(UserMapper userMapper, RoleMapper roleMapper, PermissionMapper
4747
* 大坑,必须重写此方法,不然Shiro会报错
4848
*/
4949
@Override
50-
public boolean supports(AuthenticationToken token) {
51-
return token instanceof JwtToken;
50+
public boolean supports(AuthenticationToken authenticationToken) {
51+
return authenticationToken instanceof JwtToken;
5252
}
5353

5454
/**
5555
* 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
5656
*/
5757
@Override
58-
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
58+
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
5959
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
60-
String account = JwtUtil.getClaim(principals.toString(), Constant.ACCOUNT);
60+
String account = JwtUtil.getClaim(principalCollection.toString(), Constant.ACCOUNT);
6161
UserDto userDto = new UserDto();
6262
userDto.setAccount(account);
6363
// 查询用户角色
@@ -83,8 +83,8 @@ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal
8383
* 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
8484
*/
8585
@Override
86-
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
87-
String token = (String) auth.getCredentials();
86+
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
87+
String token = (String) authenticationToken.getCredentials();
8888
// 解密获得account,用于和数据库进行对比
8989
String account = JwtUtil.getClaim(token, Constant.ACCOUNT);
9090
// 帐号为空

src/main/java/com/wang/config/shiro/jwt/JwtFilter.java

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,21 @@ protected boolean isAccessAllowed(ServletRequest request, ServletResponse respon
7979
一般使用第二种(更方便)
8080
*/
8181
// 直接返回Response信息
82-
this.response401(request, response, msg);
82+
this.response401(response, msg);
8383
return false;
8484
}
8585
} else {
8686
// 没有携带Token
87-
HttpServletRequest httpRequest = WebUtils.toHttp(request);
87+
HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
8888
// 获取当前请求类型
89-
String httpMethod = httpRequest.getMethod();
89+
String httpMethod = httpServletRequest.getMethod();
9090
// 获取当前请求URI
91-
String requestURI = httpRequest.getRequestURI();
91+
String requestURI = httpServletRequest.getRequestURI();
9292
LOGGER.info("当前请求 {} Authorization属性(Token)为空 请求类型 {}", requestURI, httpMethod);
93-
9493
// mustLoginFlag = true 开启任何请求必须登录才可访问
9594
Boolean mustLoginFlag = false;
9695
if (mustLoginFlag) {
97-
this.response401(request, response, "请先登录");
96+
this.response401(response, "请先登录");
9897
return false;
9998
}
10099
}
@@ -135,6 +134,24 @@ protected boolean executeLogin(ServletRequest request, ServletResponse response)
135134
return true;
136135
}
137136

137+
/**
138+
* 对跨域提供支持
139+
*/
140+
@Override
141+
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
142+
HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
143+
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
144+
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
145+
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
146+
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
147+
// 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
148+
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
149+
httpServletResponse.setStatus(HttpStatus.OK.value());
150+
return false;
151+
}
152+
return super.preHandle(request, response);
153+
}
154+
138155
/**
139156
* 此处为AccessToken刷新,进行判断RefreshToken是否过期,未过期就返回新的AccessToken且继续正常访问
140157
*/
@@ -163,7 +180,7 @@ private boolean refreshToken(ServletRequest request, ServletResponse response) {
163180
// 提交给UserRealm进行认证,如果错误他会抛出异常并被捕获,如果没有抛出异常则代表登入成功,返回true
164181
this.getSubject(request, response).login(jwtToken);
165182
// 最后将刷新的AccessToken存放在Response的Header中的Authorization字段返回
166-
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
183+
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
167184
httpServletResponse.setHeader("Authorization", token);
168185
httpServletResponse.setHeader("Access-Control-Expose-Headers", "Authorization");
169186
return true;
@@ -175,8 +192,8 @@ private boolean refreshToken(ServletRequest request, ServletResponse response) {
175192
/**
176193
* 无需转发,直接返回Response信息
177194
*/
178-
private void response401(ServletRequest req, ServletResponse resp, String msg) {
179-
HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
195+
private void response401(ServletResponse response, String msg) {
196+
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
180197
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
181198
httpServletResponse.setCharacterEncoding("UTF-8");
182199
httpServletResponse.setContentType("application/json; charset=utf-8");
@@ -188,22 +205,4 @@ private void response401(ServletRequest req, ServletResponse resp, String msg) {
188205
throw new CustomException("直接返回Response信息出现IOException异常:" + e.getMessage());
189206
}
190207
}
191-
192-
/**
193-
* 对跨域提供支持
194-
*/
195-
@Override
196-
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
197-
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
198-
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
199-
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
200-
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
201-
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
202-
// 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
203-
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
204-
httpServletResponse.setStatus(HttpStatus.OK.value());
205-
return false;
206-
}
207-
return super.preHandle(request, response);
208-
}
209208
}

src/main/java/com/wang/util/AesCipherUtil.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ public static String enCrypto(String str) {
5757
secureRandom.setSeed(Base64ConvertUtil.decode(encryptAESKey).getBytes());
5858
keygen.init(128, secureRandom);
5959
// SecretKey 负责保存对称密钥 生成密钥
60-
SecretKey deskey = keygen.generateKey();
60+
SecretKey desKey = keygen.generateKey();
6161
// 生成Cipher对象,指定其支持的AES算法,Cipher负责完成加密或解密工作
6262
Cipher c = Cipher.getInstance("AES");
6363
// 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式
64-
c.init(Cipher.ENCRYPT_MODE, deskey);
64+
c.init(Cipher.ENCRYPT_MODE, desKey);
6565
byte[] src = str.getBytes();
6666
// 该字节数组负责保存加密的结果
6767
byte[] cipherByte = c.doFinal(src);
@@ -100,20 +100,20 @@ public static String deCrypto(String str) {
100100
secureRandom.setSeed(Base64ConvertUtil.decode(encryptAESKey).getBytes());
101101
keygen.init(128, secureRandom);
102102
// SecretKey 负责保存对称密钥 生成密钥
103-
SecretKey deskey = keygen.generateKey();
103+
SecretKey desKey = keygen.generateKey();
104104
// 生成Cipher对象,指定其支持的AES算法,Cipher负责完成加密或解密工作
105105
Cipher c = Cipher.getInstance("AES");
106106
// 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示解密模式
107-
c.init(Cipher.DECRYPT_MODE, deskey);
108-
// 该字节数组负责保存加密的结果,先对str进行Base64解密,将16进制转换为二进制
107+
c.init(Cipher.DECRYPT_MODE, desKey);
108+
// 该字节数组负责保存解密的结果,先对str进行Base64解密,将16进制转换为二进制
109109
byte[] cipherByte = c.doFinal(HexConvertUtil.parseHexStr2Byte(Base64ConvertUtil.decode(str)));
110110
return new String(cipherByte);
111111
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
112112
LOGGER.error("getInstance()方法异常:" + e.getMessage());
113113
throw new CustomUnauthorizedException("getInstance()方法异常:" + e.getMessage());
114114
} catch (UnsupportedEncodingException e) {
115-
LOGGER.error("Base64加密异常:" + e.getMessage());
116-
throw new CustomUnauthorizedException("Base64加密异常:" + e.getMessage());
115+
LOGGER.error("Base64解密异常:" + e.getMessage());
116+
throw new CustomUnauthorizedException("Base64解密异常:" + e.getMessage());
117117
} catch (InvalidKeyException e) {
118118
LOGGER.error("初始化Cipher对象异常:" + e.getMessage());
119119
throw new CustomUnauthorizedException("初始化Cipher对象异常:" + e.getMessage());

0 commit comments

Comments
 (0)