我是靠谱客的博主 有魅力小蚂蚁,这篇文章主要介绍SpringBoot2 搭建 Shiro环境 实现权限控制登录1. Pom文件2.配置文件application.yml3.数据库配置4.获取用户数据5.Shiro的实现,现在分享给大家,希望可以做个参考。

本文搭建环境使用Springboot-2.1.3版本,数据库使用mysql,持久层使用jpa

简单实现了用户权限登录的功能,实现的比较简洁,实际项目中根据需求进行修改

1. Pom文件

首先导入需要的包

复制代码
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
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Shiro</groupId> <artifactId>Shiro</artifactId> <version>Shiro-1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.20</version> </dependency> <!-- 安全框架apache shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.3</version> </dependency> </dependencies> </project>

直接导入就可以了。

2.配置文件application.yml

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server: port: 8081 #database spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/shiro?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 username: root password: 123456 initialization-mode: always schema: classpath:schema.sql

3.数据库配置

数据源的配置

复制代码
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
package com.shiro.build.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @author FCZ * @since 2019/3/1 15:22 * 数据源配置 */ @Configuration public class DatabaseConfiguration { @ConfigurationProperties(prefix = "spring.datasource") @Bean(name = "dataSource") public DataSource dataSource() { return new DruidDataSource(); } }

druid连接池配置

复制代码
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
package com.shiro.build.config; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Druid数据源配置 */ @Configuration public class DruidConfig { @Bean public ServletRegistrationBean druidServlet() { ServletRegistrationBean reg = new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings("/druid/*"); reg.addInitParameter("loginUsername", "admin"); reg.addInitParameter("loginPassword", "admin"); return reg; } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } }

4.获取用户数据

使用jpa查询用户权限 以及用户信息,详情请查看GitHub中的代码.

5.Shiro的实现

最重要的shiro的配置实现,主要使用两个类进行配置 

复制代码
1
2
MyShiroRealm继承AuthorizingRealm,实现AuthorizingRealm的doGetAuthorizationInfo()和doGetAuthenticationInfo()方法.用于进行登录时的认证和授权。
复制代码
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
package com.shiro.build.shiro; import com.shiro.build.entity.RoleInfo; import com.shiro.build.entity.UserInfo; import com.shiro.build.respository.RoleRepository; import com.shiro.build.respository.UserRepository; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author FCZ * @since 2019/3/1 16:22 */ public class MyShiroRealm extends AuthorizingRealm { private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class); @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; /** * 权限认证 给登陆的用户授予角色和权限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("执行Shiro权限认证"); //获取当前登录输入的用户名 String loginName = (String) super.getAvailablePrincipal(principalCollection); // 到数据库查是否有此对象 UserInfo loginUserInfo = userRepository.findUserInfoByUserName(loginName); if (loginUserInfo != null) { // 取得权限信息 List<RoleInfo> roleInfoList = roleRepository.getRoleInfoByUserID(loginUserInfo.getId()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set<String> userRoles = new HashSet<>(); for(RoleInfo roleInfo : roleInfoList) { userRoles.add(roleInfo.getRoleName()); } // info.addStringPermissions(userPermissions); info.addRoles(userRoles); return info; } // 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址 return null; } /** * 登录认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //UsernamePasswordToken 对象用来存放提交的登录信息 UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; //查出是否有此用户 UserInfo loginUserInfo = userRepository.findUserInfoByUserName(token.getUsername()); if (loginUserInfo != null) { // 若存在,将此用户存放到登录认证info中 // 第一个参数为成功后存储到session中的信息 获取通过 SecurityUtils.getSubject().getPrincipal()进行获取 return new SimpleAuthenticationInfo(loginUserInfo, loginUserInfo.getPassword(), getName()); } return null; } }
复制代码
1
ShiroConfiguration类,对shiro进行配置,分别进行了对realm的注册、用户密码的加密规则以及对URL的过滤规则、和权限控制
复制代码
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
package com.shiro.build.shiro; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; /** * Created by hp on 2017/7/26. */ @Configuration public class ShiroConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class); /** * 安全管理器 * * @return */ @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(getMyRealm()); return securityManager; } /** * Realm * * @return */ @Bean(name = "myRealm") public MyShiroRealm getMyRealm() { MyShiroRealm realm = new MyShiroRealm(); realm.setCredentialsMatcher(hashedCredentialsMatcher()); return realm; } /** * 加密规则 * * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); //md5加密 散列1次 hashedCredentialsMatcher.setHashAlgorithmName("md5"); hashedCredentialsMatcher.setHashIterations(1); return hashedCredentialsMatcher; } /* @Bean public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); }*/ /** * 开启Shiro的注解支持 */ @Bean public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } /** * 开启aop注解支持 */ @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager()); return aasa; } /** * 过滤规则 * * @return */ @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorizedRole"); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // authc 必须验证后才能访问 // anon 不需要验证 filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/druid/**", "anon"); filterChainDefinitionMap.put("/api/**", "authc"); // 除了使用注解@RequiresRoles 配置权限 还可以通过下面进行配置 filterChainDefinitionMap.put("/user/**", "roles[USER]"); filterChainDefinitionMap.put("/admin/**", "roles[ADMIN]"); // "/**" 拦截 必须放到最下面 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } // 异常配置 // 使用@RequiresRoles 注解,不跳转 @Bean public SimpleMappingExceptionResolver resolver() { SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties properties = new Properties(); properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthorizedRole"); resolver.setExceptionMappings(properties); return resolver; } }

基本这样,就已经完成了项目的搭建工作。

然后启动项目调用对应接口查看权限。

登录用户 该用户有USER权限,没有ADMIN权限。

 

调用USER权限接口,查看是否调用成功

调用ADMIN权限接口,查看是否调用成功

结果显示与配置的是一致的。

下面是我搭建环境时候遇见的一些问题的总结

1. 配置未授权url后不生效

复制代码
1
2
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorizedRole");

使用这种方式配置后,访问未授权的接口,并没有跳转到"/unauthorizedRole"接口,只会提示404。

复制代码
1
2
filterChainDefinitionMap.put("/user/**", "roles[USER]"); filterChainDefinitionMap.put("/admin/**", "roles[ADMIN]");

使用这样的方式进行配置,就可以跳转到"/unauthorizedRole"接口。

或者在配置文件中,增加对异常的处理

复制代码
1
2
3
4
5
6
7
8
@Bean public SimpleMappingExceptionResolver resolver() { SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties properties = new Properties(); properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthorizedRole"); resolver.setExceptionMappings(properties); return resolver; }

这样就可以解决上述问题。

2.第一次调用登录接口会提示404错误。

因为第一次访问没有存在的cookie信息,会导致这个问题。再次请求即可。正式发布使用不会出现这种问题。

Github地址 GitHub

最后

以上就是有魅力小蚂蚁最近收集整理的关于SpringBoot2 搭建 Shiro环境 实现权限控制登录1. Pom文件2.配置文件application.yml3.数据库配置4.获取用户数据5.Shiro的实现的全部内容,更多相关SpringBoot2内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(109)

评论列表共有 0 条评论

立即
投稿
返回
顶部