一、shiro简介
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。相比较Spring Security,shiro有小巧、简单、易上手等的优点。所以很多框架都在使用shiro。Shiro包含了三个核心组件:Subject, SecurityManager 和 Realms。
1.Subject代表了当前用户的安全操作。
2.SecurityManager则管理所有用户的安全操作。它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
3.Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息
二、springboot整合shiro
1.使用maven创建一个jar项目,在pom.xml文件中添加依赖
[XML] _纯文本查看_ _复制代码_
01
02
03
04
05
06
07
08
09
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
<
`properties`>
<
`project.build.sourceEncoding>UTF-8</
project.build.sourceEncoding`>
<
`java.version>1.8</
java.version`>
</
`properties`>
<
`parent`>
<
`groupId>org.springframework.boot</
groupId`>
<
`artifactId>spring-boot-starter-parent</
artifactId`>
<
`version>1.3.5.RELEASE</
version`>
<
`relativePath/>
<!-- lookup parent from repository -->`
</
`parent`>
<
`dependencies`>
<
`dependency`>
<
`groupId>org.springframework.boot</
groupId`>
<
`artifactId>spring-boot-starter-web</
artifactId`>
</
`dependency`>
<
`dependency`>
<
`groupId>org.springframework.boot</
groupId`>
<
`artifactId>spring-boot-starter-test</
artifactId`>
<
`scope>test</
scope`>
</
`dependency`>
<
`dependency`>
<
`groupId>commons-logging</
groupId`>
<
`artifactId>commons-logging</
artifactId`>
<
`version>1.1.3</
version`>
</
`dependency`>
<
`dependency`>
<
`groupId>org.apache.shiro</
groupId`>
<
`artifactId>shiro-core</
artifactId`>
<
`version>1.2.2</
version`>
</
`dependency`>
<
`dependency`>
<
`groupId>mysql</
groupId`>
<
`artifactId>mysql-connector-java</
artifactId`>
<
`version>5.1.25</
version`>
</
`dependency`>
<
`dependency`>
<
`groupId>com.alibaba</
groupId`>
<
`artifactId>druid</
artifactId`>
<
`version>0.2.23</
version`>
</
`dependency`>
<!-- shiro权限控制框架 -->
<
`dependency`>
<
`groupId>org.apache.shiro</
groupId`>
<
`artifactId>shiro-spring</
artifactId`>
<
`version>1.3.2</
version`>
</
`dependency`>
</
`dependencies`>
2.编写MyShiroRealm类,实现AuthorizingRealm接口
[Java] _纯文本查看_ _复制代码_
01
02
03
04
05
06
07
08
09
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
public
`classMyShiroRealm
extends`AuthorizingRealm {
/**
* 授权用户权限
*/
@Override
protected
`AuthorizationInfo doGetAuthorizationInfo(`
PrincipalCollection principals) {
//获取用户
User user = (User)SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info =
`new`SimpleAuthorizationInfo();
//获取用户角色
Set<String> roleSet =
`new`HashSet<String>();
roleSet.add(
`"100002"`);
info.setRoles(roleSet);
//获取用户权限
Set<String> permissionSet =
`new`HashSet<String>();
permissionSet.add(
`"权限添加"`);
permissionSet.add(
`"权限删除"`);
info.setStringPermissions(permissionSet);
return
`info;`
}
/**
* 验证用户身份
*/
@Override
protected
`AuthenticationInfo doGetAuthenticationInfo(`
AuthenticationToken authcToken)
`throws`AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String username = token.getUsername();
String password = String.valueOf(token.getPassword());
Map<String, Object> map =
`new`HashMap<String, Object>();
map.put(
`"nickname"`, username);
//密码进行加密处理 明文为 password+name
String paw = password+username;
String pawDES = MyDES.encryptBasedDes(paw);
map.put(
`"pswd"`, pawDES);
User user =
`new`User();
user.setId(
`"112222"`);
user.setUsername(username);
user.setPassword(pawDES);
return
`new`SimpleAuthenticationInfo(user, password, getName());
}
}
3.实现ShiroConfiguration
[Java] _纯文本查看_ _复制代码_
01
02
03
04
05
06
07
08
09
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
@Configuration
public
`class`ShiroConfiguration {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
*
* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*
*/
@Bean
public
`ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {`
ShiroFilterFactoryBean shiroFilterFactoryBean =
`new`ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl(
`"/login"`);
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl(
`"/index"`);
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl(
`"/403"`);
//自定义拦截器
Map<String, Filter> filtersMap =
`new`LinkedHashMap<String, Filter>();
//限制同一帐号同时在线的个数。
//filtersMap.put("kickout", kickoutSessionControlFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// 权限控制map.
Map<String, String> filterChainDefinitionMap =
`new`LinkedHashMap<String, String>();
// 配置不会被拦截的链接 顺序判断
// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
// 从数据库获取动态的权限
// filterChainDefinitionMap.put("/add", "perms[权限添加]");
// <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//logout这个拦截器是shiro已经实现好了的。
// 从数据库获取
/*List<SysPermissionInit> list = sysPermissionInitService.selectAll();
for (SysPermissionInit sysPermissionInit : list) {
filterChainDefinitionMap.put(sysPermissionInit.getUrl(),
sysPermissionInit.getPermissionInit());
}*/
shiroFilterFactoryBean
.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm());
// 自定义缓存实现 使用redis
//securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
//securityManager.setSessionManager(sessionManager());
//注入记住我管理器;
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
public MyShiroRealm myShiroRealm(){
return new MyShiroRealm();
}
/**
* cookie对象;
* @return
*/
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//<!-- 记住我cookie生效时间30天 ,单位秒;-->
simpleCookie.setMaxAge(2592000);
return simpleCookie;
}
/**
* cookie管理对象;记住我功能
* @return
*/
public
`CookieRememberMeManager rememberMeManager(){`
CookieRememberMeManager cookieRememberMeManager =
`new`CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode(
`"3AvVhmFLUs0KTA3Kprsdag=="`));
return
`cookieRememberMeManager;`
}
}
4.编写LoginController类测试Shiro
[Java] _纯文本查看_ _复制代码_
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
@RestController
public
`class`LoginController {
@RequestMapping
`(value="/login"
,method=RequestMethod.POST)`
public
`String login(String username, String password,String vcode,Boolean rememberMe){`
System.out.println(username);
UsernamePasswordToken token =
`new`UsernamePasswordToken(username, password,rememberMe);
SecurityUtils.getSubject().login(token);
return
`"loginSuccess"`;
}
@RequestMapping
`(value="/index"
,method=RequestMethod.GET)`
public
`String home(){`
Subject subject = SecurityUtils.getSubject();
User principal = (User)subject.getPrincipal();
return
`"Home"`;
}
}