Shiro

shiro实现权限

其他框架:

sprintSecurity(还未研究,据说类似)

配置步骤:

  1. 导入maven
  2. 添加ShiroConfig
  3. 创建UserRealm

注意:

  • 在过滤器创建的时候是 LinkedHashMap 千万注意, 不然通配符不会匹配,会被覆盖掉
  • 过滤器创建时可设置未授权跳转页面,不适用于分离项目
  • 过滤工厂创建的时候可以放入自定义拦截器,用于项目自己的业务
  • 可以在subject.login()之前,通过对session设置来修改登录过期时间

核心:

  • Subject 获取当前对象
  • token可用username,password生成
  • 可使用Md5Hash进行加密
  • 在调用login后通过捕获异常来区别不同的登录情况
1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
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
package com.jcDemo.shiro;

import com.jcDemo.interceptor.MyFormAuthenticationFilter;
import org.apache.shiro.mgt.DefaultSecurityManager;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;

/**
*@author:gao_quansui
*@user:ASUS
*@date:2022/9/21- 10:57
*@projectName:jc_demo
*/

@Configuration
public class ShiroConfig {

@Bean
public UserRealm userRealm() {
return new UserRealm();
}

@Bean(name = "filterShiroFilterRegistrationBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("SecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
//1.创建过滤工厂
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("MyFormAuthenticationFilter", new MyFormAuthenticationFilter());
bean.setFilters(filters);
//2.设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);

//3.配置未授权跳转页面
// bean.setLoginUrl("/test");
// bean.setLoginUrl(null);

//4.设置filter
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/api/user/login", "anon");

filterMap.put("/api/**", "MyFormAuthenticationFilter");

bean.setFilterChainDefinitionMap(filterMap);

return bean;
}

@Bean(name = "SecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}

//开启shiro注解
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}

//开启aop注解支持
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
}

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
package com.jcDemo.shiro;

import com.jcDemo.entity.entities.User;
import com.jcDemo.entity.vo.UidUsernameName;
import com.jcDemo.service.user.RoleService;
import com.jcDemo.service.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
*@author:gao_quansui
*@user:ASUS
*@date:2022/9/21- 10:07
*@projectName:jc_demo
*/
@Slf4j
public class UserRealm extends AuthorizingRealm {

@Autowired
UserService userService;

@Autowired
RoleService roleService;

//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.info("执行====================授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

// Object data = roleService.getUserRoleById(1).getData();
// info.addStringPermission("");

Subject subject = SecurityUtils.getSubject();

User user = (User) subject.getPrincipal(); //下面方法传上来的user对象

//获取当前用户的权限数组
List<UidUsernameName> uidUsernameName = (List<UidUsernameName>) roleService.getUserRoleById(user.getId());

//遍历添加权限
uidUsernameName.forEach(e -> {
info.addStringPermission(e.getRoleName());
log.info("username:{}-------roleName:{}", e.getUsername(), e.getRoleName());
});

return info;
}

//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

UsernamePasswordToken userToken = (UsernamePasswordToken) token;

User user = userService.getUserByName(userToken.getUsername());

if (user == null) {
return null;
}

log.info("认证");

Subject subject = SecurityUtils.getSubject();
// subject.isPermitted("123");
// subject.hasRole("authc");

// if(!userToken.getUsername().equals(user.getUsername())){
// return null; //会在controller中捕获
// }
//
return new SimpleAuthenticationInfo(user, user.getPassword(), ""); //验证密码
// return null;
}
}

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
package com.jcDemo.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jcDemo.entity.res.Result;
import com.jcDemo.entity.res.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.springframework.util.StringUtils;

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;

/**
*@author:gao_quansui
*@user:ASUS
*@date:2022/9/28- 10:07
*@projectName:jc_demo
*/
@Slf4j
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
log.info("被shiro拦截啦=================================");

PrintWriter out = null;
try {
HttpServletResponse res = (HttpServletResponse) response;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
out = response.getWriter();
if (res.getStatus() == HttpServletResponse.SC_UNAUTHORIZED) {
out.println(JSON.toJSONString(new Result(ResultCode.UNAUTHORISE)));
} else {
if (StringUtils.isEmpty(((ShiroHttpServletRequest) request).getHeader("Authorization"))) {
log.info("未登录");
out.write(JSONObject.toJSONString(new Result(ResultCode.UNAUTHENTICATED, "")));
} else {
log.info("session已过期");
out.write(JSONObject.toJSONString(new Result(ResultCode.EXPIREDSESSION, "")));
}
}
} catch (IOException e) {
log.info("session异常");
} finally {
if (out != null) {
out.close();
}
}
return Boolean.FALSE;
}

@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
return super.isAccessAllowed(request, response, mappedValue);
}
}