一、概念
Shiro是一个Java安全框架,可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。
**Subject:**即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。
**SecurityManager:**管理所有Subject,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。
**Realm:**域,Shiro从从Realm获取安全数据(如用户、角色、权限),可以看成数据库。
认证流程:
使用流程:
1. 自定义realm
2.构建SecurityManager环境
3.提交认证,将携带的信息储存在 UsernamePasswordToken中
1
2 1UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
2
4.获取subject
1
2 1Subject subject = SecurityUtils.getSubject();
2
5.登录
1
2 1subject.login(usernamePasswordToken);
2
二、代码
代码层级
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 1<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">
2 <modelVersion>4.0.0</modelVersion>
3 <artifactId>springboot-shiro-10095</artifactId>
4
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.0.2.RELEASE</version>
9 <relativePath/>
10 </parent>
11 <dependencies>
12 <dependency>
13 <groupId>org.springframework.boot</groupId>
14 <artifactId>spring-boot-devtools</artifactId>
15 </dependency>
16 <dependency>
17 <groupId>org.springframework.boot</groupId>
18 <artifactId>spring-boot-starter-web</artifactId>
19 </dependency>
20 <dependency>
21 <groupId>org.springframework.boot</groupId>
22 <artifactId>spring-boot-starter-data-jpa</artifactId>
23 </dependency>
24 <dependency>
25 <groupId>mysql</groupId>
26 <artifactId>mysql-connector-java</artifactId>
27 <version>5.1.44</version>
28 <scope>runtime</scope>
29 </dependency>
30 <dependency>
31 <groupId>com.alibaba</groupId>
32 <artifactId>druid</artifactId>
33 <version>1.1.4</version>
34 </dependency>
35 <!-- shiro -->
36 <dependency>
37 <groupId>org.apache.shiro</groupId>
38 <artifactId>shiro-spring</artifactId>
39 <version>1.3.2</version>
40 </dependency>
41 </dependencies>
42
43 <build>
44 <plugins>
45 <plugin>
46 <groupId>org.apache.maven.plugins</groupId>
47 <artifactId>maven-compiler-plugin</artifactId>
48 <configuration>
49 <source>1.8</source>
50 <target>1.8</target>
51 </configuration>
52 </plugin>
53 </plugins>
54 </build>
55
56</project>
57
2.application.yml
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 1server:
2 port: 10095
3spring:
4 application:
5 name: shiro
6# zipkin:
7# base-url: http://127.0.0.1:10092
8#eureka
9#eureka:
10# client:
11# service-url:
12# defaultZone: http://localhost:10090/eureka/
13 datasource:
14 driver-class-name: com.mysql.jdbc.Driver
15 url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8
16 username: root
17 password: root
18 type: com.alibaba.druid.pool.DruidDataSource
19 jpa:
20 show-sql: true
21 hibernate:
22 ddl-auto: update
23 http:
24 encoding:
25 charset: utf-8
26 enabled: true
27
3.关于shiro的表5张,利用JPA自动生成
(1)User 用户表
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 1/**
2 * All rights Reserved
3 * @Title: User.java
4 * @Package com.yanwu.www.entity
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:05:58
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.entity;
12
13import java.util.List;
14
15import javax.persistence.Entity;
16import javax.persistence.GeneratedValue;
17import javax.persistence.GenerationType;
18import javax.persistence.Id;
19
20/**
21 * @ClassName: User
22 * @Description:TODO(这里用一句话描述这个类的作用)
23 * @author: harvey
24 * @date: 2018年8月30日 下午2:05:58
25 *
26 * @Copyright: 2018
27 */
28@Entity(name="user")
29public class User {
30 @Id
31 @GeneratedValue(strategy = GenerationType.AUTO)
32 private Long id;
33
34 private String name;
35 private String password;
36
37 public Long getId() {
38 return id;
39 }
40
41 public void setId(Long id) {
42 this.id = id;
43 }
44
45 public String getName() {
46 return name;
47 }
48
49 public void setName(String name) {
50 this.name = name;
51 }
52
53 public String getPassword() {
54 return password;
55 }
56
57 public void setPassword(String password) {
58 this.password = password;
59 }
60
61
62}
63
(2)Role 角色表
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 1/**
2 * All rights Reserved
3 * @Title: Role.java
4 * @Package com.yanwu.www.entity
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:07:43
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.entity;
12
13import javax.persistence.Entity;
14import javax.persistence.GeneratedValue;
15import javax.persistence.GenerationType;
16import javax.persistence.Id;
17
18/**
19 * @ClassName: Role
20 * @Description:TODO(这里用一句话描述这个类的作用)
21 * @author: harvey
22 * @date: 2018年8月30日 下午2:07:43
23 *
24 * @Copyright: 2018
25 */
26@Entity
27public class Role {
28 @Id
29 @GeneratedValue(strategy = GenerationType.AUTO)
30 private Long id;
31 private String roleName;
32
33 public Long getId() {
34 return id;
35 }
36
37 public void setId(Long id) {
38 this.id = id;
39 }
40
41 public String getRoleName() {
42 return roleName;
43 }
44
45 public void setRoleName(String roleName) {
46 this.roleName = roleName;
47 }
48}
49
(3)Permission 权限表
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 1/**
2 * All rights Reserved
3 * @Title: Permission.java
4 * @Package com.yanwu.www.entity
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:12:42
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.entity;
12
13import javax.persistence.Entity;
14import javax.persistence.GeneratedValue;
15import javax.persistence.GenerationType;
16import javax.persistence.Id;
17
18/**
19 * @ClassName: Permission
20 * @Description:TODO(这里用一句话描述这个类的作用)
21 * @author: harvey
22 * @date: 2018年8月30日 下午2:12:42
23 *
24 * @Copyright: 2018
25 */
26@Entity
27public class Permission {
28
29 @Id
30 @GeneratedValue(strategy = GenerationType.AUTO)
31 private Long id;
32
33 private String permission;
34
35 public Long getId() {
36 return id;
37 }
38
39 public void setId(Long id) {
40 this.id = id;
41 }
42
43 public String getPermission() {
44 return permission;
45 }
46
47 public void setPermission(String permission) {
48 this.permission = permission;
49 }
50}
51
(4)UserRole 用户和角色关联
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 1/**
2 * All rights Reserved
3 * @Title: UserRole.java
4 * @Package com.yanwu.www.entity
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:15:24
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.entity;
12
13import javax.persistence.Entity;
14import javax.persistence.GeneratedValue;
15import javax.persistence.GenerationType;
16import javax.persistence.Id;
17
18/**
19 * @ClassName: UserRole
20 * @Description:TODO(这里用一句话描述这个类的作用)
21 * @author: harvey
22 * @date: 2018年8月30日 下午2:15:24
23 *
24 * @Copyright: 2018
25 */
26@Entity
27public class UserRole {
28 @Id
29 @GeneratedValue(strategy = GenerationType.AUTO)
30 private Long id;
31
32 private String userId;
33
34 private String roleId;
35
36 public Long getId() {
37 return id;
38 }
39
40 public void setId(Long id) {
41 this.id = id;
42 }
43
44 public String getUserId() {
45 return userId;
46 }
47
48 public void setUserId(String userId) {
49 this.userId = userId;
50 }
51
52 public String getRoleId() {
53 return roleId;
54 }
55
56 public void setRoleId(String roleId) {
57 this.roleId = roleId;
58 }
59}
60
(5)RolePermission 角色和权限关联
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 1/**
2 * All rights Reserved
3 * @Title: RolePermission.java
4 * @Package com.yanwu.www.entity
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:17:02
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.entity;
12
13import javax.persistence.Entity;
14import javax.persistence.GeneratedValue;
15import javax.persistence.GenerationType;
16import javax.persistence.Id;
17
18/**
19 * @ClassName: RolePermission
20 * @Description:TODO(这里用一句话描述这个类的作用)
21 * @author: harvey
22 * @date: 2018年8月30日 下午2:17:02
23 *
24 * @Copyright: 2018
25 */
26@Entity
27public class RolePermission {
28
29 @Id
30 @GeneratedValue(strategy = GenerationType.AUTO)
31 private Long id;
32
33 private String roleId;
34
35 private String permissionId;
36
37 public Long getId() {
38 return id;
39 }
40
41 public void setId(Long id) {
42 this.id = id;
43 }
44
45 public String getRoleId() {
46 return roleId;
47 }
48
49 public void setRoleId(String roleId) {
50 this.roleId = roleId;
51 }
52
53 public String getPermissionId() {
54 return permissionId;
55 }
56
57 public void setPermissionId(String permissionId) {
58 this.permissionId = permissionId;
59 }
60
61}
62
4.自定义realm(需要继承AuthorizingRealm)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 1/**
2 * All rights Reserved
3 * @Title: UserRealm.java
4 * @Package com.yanwu.www.config
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:48:54
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.config;
12
13import java.util.List;
14
15import org.apache.shiro.authc.AuthenticationException;
16import org.apache.shiro.authc.AuthenticationInfo;
17import org.apache.shiro.authc.AuthenticationToken;
18import org.apache.shiro.authc.SimpleAuthenticationInfo;
19import org.apache.shiro.authc.UnknownAccountException;
20import org.apache.shiro.authc.UsernamePasswordToken;
21import org.apache.shiro.authz.AuthorizationInfo;
22import org.apache.shiro.authz.SimpleAuthorizationInfo;
23import org.apache.shiro.crypto.hash.SimpleHash;
24import org.apache.shiro.realm.AuthorizingRealm;
25import org.apache.shiro.subject.PrincipalCollection;
26import org.apache.shiro.util.ByteSource;
27import org.springframework.beans.factory.annotation.Autowired;
28import org.springframework.stereotype.Component;
29
30import com.yanwu.www.entity.Permission;
31import com.yanwu.www.entity.Role;
32import com.yanwu.www.entity.User;
33import com.yanwu.www.repository.PermissionRipository;
34import com.yanwu.www.repository.RoleRipository;
35import com.yanwu.www.repository.UserRipository;
36
37/**
38 * @ClassName: UserRealm
39 * @Description: 自定义realm
40 * @author: harvey
41 * @date: 2018年8月30日 下午2:48:54
42 *
43 * @Copyright: 2018
44 */
45@Component
46public class MyShiroRealm extends AuthorizingRealm{
47
48 @Autowired
49 private UserRipository userRipository;
50
51 @Autowired
52 private RoleRipository roleRipository;
53
54 @Autowired
55 private PermissionRipository permissionRipository;
56
57 /**
58 * <p>Title: doGetAuthorizationInfo</p>
59 * <p>Description: </p>
60 * @param arg0
61 * @return
62 * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
63 */
64 @Override
65 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
66
67 //获取登录用户名
68 String username= (String) principalCollection.getPrimaryPrincipal();
69 //查询用户名称
70 User user = userRipository.findByName(username);
71
72 //添加角色和权限
73 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
74 List<Role> roles = roleRipository.findRolesByUserId(user.getId().toString());
75 for(Role role : roles){
76 // 添加角色
77 simpleAuthorizationInfo.addRole(role.getRoleName());
78 for(Permission permission : permissionRipository.findPermissionsByRoleId(role.getId().toString())){
79 // 添加权限
80 simpleAuthorizationInfo.addStringPermission(permission.getPermission());
81 }
82 }
83
84 return simpleAuthorizationInfo;
85
86 }
87
88 /**
89 * <p>Title: doGetAuthenticationInfo</p>
90 * <p>Description: </p>
91 * @param arg0
92 * @return
93 * @throws AuthenticationException
94 * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
95 */
96 @Override
97 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
98
99 // 1.把AuthenticationToken转为UsernamePasswordToken对象
100 UsernamePasswordToken upToken = (UsernamePasswordToken) token;
101
102 // 2.从UsernamePasswordToken获取username
103 String userName = upToken.getUsername();
104
105 // 3.调用数据库方法,从数据库中查询username对应的用户记录
106 System.out.println("从数据库中获取信息userName:" + userName + "所对应信息");
107 User user = userRipository.findByName(userName);
108
109 // 4.若用户不存在,则可以抛出异常
110 if (null == user) {
111 throw new UnknownAccountException("用户不存在");
112 }
113
114 // 5.根据用户情况,来构建AuthenticationInfo对象并返回,通常使用的实现类是SimpleAuthenticationInfo
115
116 // 1)principal,用户名,认证实体,可以是实体,也可以是数据表对应的实体类对象
117 Object principal = userName;
118
119 // 2)credential,密码,明文密码,即构建UsernamePasswordToken对象时的密码
120 Object credentials = user.getPassword().toString();
121
122 // 3)realmName:当前realm对象的name,调用父类的getName即可
123 String realmName = getName();
124
125 // 4.盐值(避免同一密码加密时产生相同的字符串,一般是用用户名做盐值)
126 ByteSource credentialsSalt = ByteSource.Util.bytes(userName);
127
128 // 不加密
129 //SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
130
131 // 加密
132 SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal,credentials, credentialsSalt, realmName);
133
134 return info;
135 }
136
137
138 // 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
139 public static void main(String[] args) {
140 String algorithmName="MD5";
141 Object source="1234";
142 Object salt=ByteSource.Util.bytes("user2");
143 int hashIterations=1024;
144 Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
145 System.out.println(result);
146 }
147
148}
149
5.shiro配置类
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 1/**
2 * All rights Reserved
3 * @Title: ShiroConfig.java
4 * @Package com.yanwu.www.config
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:47:16
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.config;
12
13import java.util.HashMap;
14import java.util.Map;
15
16import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
17import org.apache.shiro.mgt.SecurityManager;
18import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
19import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
20import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
21import org.springframework.context.annotation.Bean;
22import org.springframework.context.annotation.Configuration;
23
24/**
25 * @ClassName: ShiroConfig
26 * @Description:shiro配置类
27 * @author: harvey
28 * @date: 2018年8月30日 下午2:47:16
29 *
30 * @Copyright: 2018
31 */
32@Configuration
33public class ShiroConfig {
34
35
36 /**
37 * 密码校验规则HashedCredentialsMatcher
38 * 这个类是为了对密码进行编码的 ,
39 * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
40 * 这个类也负责对form里输入的密码进行编码
41 * 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
42 */
43 @Bean
44 public HashedCredentialsMatcher hashedCredentialsMatcher() {
45 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
46 //指定加密方式为MD5
47 credentialsMatcher.setHashAlgorithmName("MD5");
48 //加密次数
49 credentialsMatcher.setHashIterations(1024);
50 credentialsMatcher.setStoredCredentialsHexEncoded(true);
51 return credentialsMatcher;
52 }
53
54 //将自己的验证方式加入容器
55 @Bean
56 public MyShiroRealm myShiroRealm() {
57 MyShiroRealm myShiroRealm = new MyShiroRealm();
58
59 // 设置加密方式
60 myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
61
62 return myShiroRealm;
63 }
64
65 //权限管理,配置主要是Realm的管理认证
66 @Bean
67 public SecurityManager securityManager() {
68 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
69 securityManager.setRealm(myShiroRealm());
70
71 return securityManager;
72 }
73
74 //Filter工厂,设置对应的过滤条件和跳转条件
75 @Bean
76 public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
77 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
78 shiroFilterFactoryBean.setSecurityManager(securityManager);
79 Map<String,String> map = new HashMap<String, String>();
80
81 //anon表示可以匿名访问,authc表示需要认证
82 //登出
83 map.put("/logout","anon");
84 //对所有用户认证
85 map.put("/**","authc");
86 //登录
87 shiroFilterFactoryBean.setLoginUrl("/login");
88
89 //首页
90 shiroFilterFactoryBean.setSuccessUrl("/index");
91
92 //错误页面,认证不通过跳转
93 shiroFilterFactoryBean.setUnauthorizedUrl("/error");
94
95 shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
96 return shiroFilterFactoryBean;
97 }
98
99 //加入注解的使用,不加入这个注解不生效
100 @Bean
101 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
102 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
103 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
104 return authorizationAttributeSourceAdvisor;
105 }
106
107}
108
6.Repositoty
(1)BaseRepository
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 1package com.yanwu.www.repository;
2
3import java.io.Serializable;
4
5import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
6import org.springframework.data.repository.NoRepositoryBean;
7import org.springframework.data.repository.PagingAndSortingRepository;
8/**
9 *
10 * @ClassName: BaseRepository
11 * @Description:TODO(这里用一句话描述这个类的作用)
12 * @author: harvey
13 * @date: 2018年8月30日 下午2:21:18
14 *
15 * @param <T>
16 * @param <I>
17 * @Copyright: 2018
18 */
19@NoRepositoryBean
20public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>,JpaSpecificationExecutor<T>{
21
22}
23
(2)UserRipository
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 1/**
2 * All rights Reserved
3 * @Title: UserRipository.java
4 * @Package com.yanwu.www.repository
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:20:19
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.repository;
12
13import org.springframework.stereotype.Repository;
14
15import com.yanwu.www.entity.User;
16
17/**
18 * @ClassName: UserRipository
19 * @Description:TODO(这里用一句话描述这个类的作用)
20 * @author: harvey
21 * @date: 2018年8月30日 下午2:20:19
22 *
23 * @Copyright: 2018
24 */
25@Repository
26public interface UserRipository extends BaseRepository<User, Long>{
27
28 User findByName(String username);
29}
30
(3)RoleRipository
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 1/**
2 * All rights Reserved
3 * @Title: UserRipository.java
4 * @Package com.yanwu.www.repository
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:20:19
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.repository;
12
13import java.util.List;
14
15import org.springframework.data.jpa.repository.Query;
16import org.springframework.stereotype.Repository;
17
18import com.yanwu.www.entity.Role;
19
20/**
21 * @ClassName: UserRipository
22 * @Description:TODO(这里用一句话描述这个类的作用)
23 * @author: harvey
24 * @date: 2018年8月30日 下午2:20:19
25 *
26 * @Copyright: 2018
27 */
28@Repository
29public interface RoleRipository extends BaseRepository<Role, Long>{
30
31 @Query(value = "select distinct r.* from role r inner join role_permission rp on rp.role_id = r.id inner join user_role ur on ur.role_id = r.id where ur.user_id =?1" ,nativeQuery=true)
32 List<Role> findRolesByUserId(String userId);
33}
34
(4)PermissionRipository
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 1/**
2 * All rights Reserved
3 * @Title: UserRipository.java
4 * @Package com.yanwu.www.repository
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:20:19
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.repository;
12
13import java.util.List;
14
15import org.springframework.data.jpa.repository.Query;
16import org.springframework.stereotype.Repository;
17
18import com.yanwu.www.entity.Permission;
19
20/**
21 * @ClassName: UserRipository
22 * @Description:TODO(这里用一句话描述这个类的作用)
23 * @author: harvey
24 * @date: 2018年8月30日 下午2:20:19
25 *
26 * @Copyright: 2018
27 */
28@Repository
29public interface PermissionRipository extends BaseRepository<Permission, Long>{
30
31 @Query(value = "select distinct p.* from permission p inner join role_permission rp on rp.permission_id = p.id inner join role r on r.id = rp.role_id where r.id =?1" ,nativeQuery=true)
32 List<Permission> findPermissionsByRoleId(String roleId);
33}
34
7.service
(1)UserService
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 1/**
2 * All rights Reserved
3 * @Title: UserService.java
4 * @Package com.yanwu.www.service
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:25:11
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.service;
12
13/**
14 * @ClassName: UserService
15 * @Description:TODO(这里用一句话描述这个类的作用)
16 * @author: harvey
17 * @date: 2018年8月30日 下午2:25:11
18 *
19 * @Copyright: 2018
20 */
21public interface UserService {
22 /**
23 *
24 * @Title: login
25 * @Description: 用户登录
26 * @param username
27 * @param password
28 * @return
29 * @return: String
30 */
31 String login(String username,String password);
32
33 /**
34 *
35 * @Title: logout
36 * @Description: 用户登出
37 * @return
38 * @return: String
39 */
40 String logout();
41}
42
(2)UserServiceImpl
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 1/**
2 * All rights Reserved
3 * @Title: UserServiceImpl.java
4 * @Package com.yanwu.www.service
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午2:27:15
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.service;
12
13import org.apache.shiro.SecurityUtils;
14import org.apache.shiro.authc.AuthenticationException;
15import org.apache.shiro.authc.UnknownAccountException;
16import org.apache.shiro.authc.UsernamePasswordToken;
17import org.apache.shiro.subject.Subject;
18import org.springframework.stereotype.Component;
19import org.springframework.util.StringUtils;
20
21/**
22 * @ClassName: UserServiceImpl
23 * @Description:TODO(这里用一句话描述这个类的作用)
24 * @author: harvey
25 * @date: 2018年8月30日 下午2:27:15
26 *
27 * @Copyright: 2018
28 */
29@Component
30public class UserServiceImpl implements UserService {
31
32 /**
33 * <p>Title: login</p>
34 * <p>Description: </p>
35 * @param username
36 * @param password
37 * @see com.yanwu.www.service.UserService#login(java.lang.String, java.lang.String)
38 */
39 @Override
40 public String login(String username, String password) {
41
42 if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
43 throw new UnknownAccountException("账号或者密码为空");
44 }
45
46 UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
47
48 Subject subject = SecurityUtils.getSubject();
49
50 try{
51 subject.login(usernamePasswordToken);
52
53 // 设置闲置session时间
54 subject.getSession().setTimeout(5*1000);
55 return "login ok";
56 }catch( AuthenticationException e){
57 System.out.println("==========");
58 System.out.println(e.getMessage());
59 }
60
61 return "login failure";
62
63 }
64
65 /**
66 * <p>Title: logout</p>
67 * <p>Description: </p>
68 * @return
69 * @see com.yanwu.www.service.UserService#logout()
70 */
71 @Override
72 public String logout() {
73
74 Subject subject = SecurityUtils.getSubject();
75
76 subject.logout();
77
78 return "logout ok";
79 }
80}
81
8.controller
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 1/**
2 * All rights Reserved
3 * @Title: UserController.java
4 * @Package com.yanwu.www.controller
5 * @Description: TODO(用一句话描述该文件做什么)
6 * @author: harvey
7 * @date: 2018年8月30日 下午3:31:43
8 * @version V1.0
9 * @Copyright: 2018
10 */
11package com.yanwu.www.controller;
12
13import org.apache.shiro.authz.annotation.RequiresRoles;
14import org.springframework.beans.factory.annotation.Autowired;
15import org.springframework.web.bind.annotation.RequestMapping;
16import org.springframework.web.bind.annotation.RequestMethod;
17import org.springframework.web.bind.annotation.RestController;
18
19import com.yanwu.www.service.UserService;
20
21/**
22 * @ClassName: UserController
23 * @Description:TODO(这里用一句话描述这个类的作用)
24 * @author: harvey
25 * @date: 2018年8月30日 下午3:31:43
26 *
27 * @Copyright: 2018
28 */
29@RestController
30public class UserController {
31
32 @Autowired
33 private UserService userService;
34
35 //登录
36 @RequestMapping(value = "/login")
37 public String login(String username,String password){
38
39 String status = userService.login(username, password);
40
41 return status;
42 }
43
44 //首页
45 @RequestMapping(value = "/index")
46 public String index(){
47
48 return "index";
49 }
50
51 //登出
52 @RequestMapping(value = "/logout")
53 public String logout(){
54
55 userService.logout();
56
57 return "logout";
58 }
59
60 //错误页面展示
61 @RequestMapping(value = "/error",method = RequestMethod.POST)
62 public String error(){
63 return "error ok!";
64 }
65
66 // 测试shiro注解
67 @RequestMapping(value = "/test",method = RequestMethod.GET)
68 @RequiresRoles(value={"admin"})
69 public String test(){
70 return "test ok!";
71 }
72
73
74}
75
三、注意点
加密
本博客已经配置,需要在自定义realm,securityManager进行修改,如下配置如何获得加密后的字符串
1
2
3
4
5
6
7
8
9
10
11 1// 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
2public static void main(String[] args) {
3 String algorithmName="MD5";
4 Object source="1234";
5 // 加盐
6 Object salt=ByteSource.Util.bytes("user2");
7 int hashIterations=1024;
8 Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
9 System.out.println(result);
10}
11