前言
shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能.
而springboot作为一个开源框架,必然提供了和shiro整合的功能!
之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mongodb中,这个比较符合mongodb的设计初衷,而且在分布式项目中mongodb也作为一个中间层,用来很好很方便解决分布式环境下的session同步的问题
自从SpringBoot问世之后我的项目基本上能用SpringBoot的就会用SpringBoot,用MAVEN做统一集中管理也很方便,虽然SpringBoot也提供了一套权限安全框架Spring Security,但是相对来说还是不是太好用,所以还是用Shiro来的方便一点,SpringBoot集成Shiro要比Spring MVC要简单的多,至少没有一堆XML配置,看起来更清爽,那么接下来我们就开始集成。
方法如下:
第一步必然是在MAVEN中先添加Shiro和mongo的依赖,我用的Shiro版本是
1
|
<shiro.version> 1.2 . 3 </shiro.version>
|
添加依赖:
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
|
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version> 3.0 . 0 </version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version> 1.7 . 0 .RELEASE</version>
</dependency>
|
然后在application.xml或yml中配置mongodb
1
2
3
|
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.port=27017
spring.data.mongodb.database=SHIRO_INFO
|
配置完成之后我们开始正式写Shiro认证的代码,先自定义一个鉴权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
|
public class ShiroDbRealm extends AuthorizingRealm {
/**
* 用户信息操作
*/
private SystemUserService systemUserService;
public ShiroDbRealm() {}
public ShiroDbRealm(SystemUserService systemUserService) {
this .systemUserService = systemUserService;
}
/**
* 授权信息
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
if ( null != info && !CollectionUtils.isEmpty(info.getRoles())
&& !CollectionUtils.isEmpty(info.getStringPermissions())) {
return info;
}
return null ;
}
/**
* 认证信息
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String userName = token.getUsername();
if (userName != null && ! "" .equals(userName)) {
SystemUser key = new SystemUser();
key.setLoginName(token.getUsername());
key.setPassword(String.valueOf(token.getPassword()));
SystemUser user = systemUserService.login(key);
if (user != null ) {
Subject userTemp = SecurityUtils.getSubject();
userTemp.getSession().setAttribute( "userId" , user.getId());
userTemp.getSession().setAttribute( "userName" , user.getUserName());
return new SimpleAuthenticationInfo(user.getLoginName(), user.getPassword(), getName());
}
}
return null ;
}
}
|
存储session进mongodb的Repository和实现:
1
2
3
4
5
6
7
8
|
public interface ShiroSessionRepository {
/**
*
* @param session
*/
void saveSession(Session session);
......
}
|
MongoDBSessionRepository.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class MongoDBSessionRepository implements ShiroSessionRepository {
private MongoTemplate mongoTemplate;
public MongoDBSessionRepository() {}
public MongoDBSessionRepository(MongoTemplate mongoTemplate) {
this .mongoTemplate = mongoTemplate;
}
@Override
public void saveSession(Session session) {
if (session == null || session.getId() == null ) {
return ;
}
SessionBean bean = new SessionBean();
bean.setKey(getSessionKey(session.getId()));
bean.setValue(SerializeUtil.serialize(session));
bean.setPrincipal( null );
bean.setHost(session.getHost());
bean.setStartTimestamp(session.getStartTimestamp());
bean.setLastAccessTime(session.getLastAccessTime());
bean.setTimeoutTime(getTimeoutTime(session.getStartTimestamp(), session.getTimeout()));
mongoTemplate.insert(bean);
}
......
}
|
ShiroSessionDAO.java
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
|
public class ShiroSessionDAO extends AbstractSessionDAO {
/**
* 日志记录器
*/
private static final Logger log = LoggerFactory.getLogger(ShiroSessionDAO. class );
/**
* 数据库存储
*/
private ShiroSessionRepository shiroSessionRepository;
/**
*
* @return
*/
public ShiroSessionRepository getShiroSessionRepository() {
return shiroSessionRepository;
}
/**
*
* @param shiroSessionRepository
*/
public void setShiroSessionRepository(ShiroSessionRepository shiroSessionRepository) {
this .shiroSessionRepository = shiroSessionRepository;
}
@Override
public void update(Session session) throws UnknownSessionException {
getShiroSessionRepository().updateSession(session);
}
@Override
public void delete(Session session) {
if (session == null ) {
log.error( "session can not be null,delete failed" );
return ;
}
Serializable id = session.getId();
if (id != null ) {
getShiroSessionRepository().deleteSession(id);
}
}
@Override
public Collection<Session> getActiveSessions() {
return getShiroSessionRepository().getAllSessions();
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this .generateSessionId(session);
this .assignSessionId(session, sessionId);
getShiroSessionRepository().saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
return getShiroSessionRepository().getSession(sessionId);
}
}
|
OK!所有基础类已经完成,最后写一个config用来全部初始化和配置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
|
@Configuration
public class ShiroConfig {
@Resource
private MongoTemplate mongoTemplate;
@Resource
private SystemUserService systemUserService; // 这是用来判断用户名和密码的service
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl( "/login" );
shiroFilterFactoryBean.setSuccessUrl( "/index" );
shiroFilterFactoryBean.setUnauthorizedUrl( "/403" );
// 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put( "/static/**" , "anon" );
filterChainDefinitionMap.put( "/ajaxLogin" , "anon" );
filterChainDefinitionMap.put( "/libs/**" , "anon" );
filterChainDefinitionMap.put( "/images/**" , "anon" );
filterChainDefinitionMap.put( "/logout" , "logout" );
filterChainDefinitionMap.put( "/**" , "authc" ); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor adv = new AuthorizationAttributeSourceAdvisor();
adv.setSecurityManager(securityManager);
return adv;
}
@Bean
public DefaultWebSecurityManager securityManager(DefaultWebSessionManager sessionManager,
ShiroDbRealm myShiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm);
securityManager.setSessionManager(sessionManager);
return securityManager;
}
/**
* 身份认证realm; (这里传递systemUserService给自定义的ShiroDbRealm初始化)
*
* @return
*/
@Bean
public ShiroDbRealm myShiroRealm() {
ShiroDbRealm myShiroRealm = new ShiroDbRealm(systemUserService);
return myShiroRealm;
}
@Bean
public DefaultWebSessionManager sessionManager(ShiroSessionDAO shiroSessionDao) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(1800000l);
sessionManager.setDeleteInvalidSessions( true ); sessionManager.setSessionValidationSchedulerEnabled( true );
sessionManager.setSessionDAO(shiroSessionDao);
sessionManager.setSessionIdCookieEnabled( true );
SimpleCookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setHttpOnly( true );
cookie.setMaxAge( 1800000 );
sessionManager.setSessionIdCookie(cookie);
return sessionManager;
}
@Bean
public ShiroSessionDAO shiroSessionDao(MongoDBSessionRepository shiroSessionRepository) {
ShiroSessionDAO dao = new ShiroSessionDAO();
dao.setShiroSessionRepository(shiroSessionRepository);
return dao;
}
@Bean
MongoDBSessionRepository shiroSessionRepository() {
MongoDBSessionRepository resp = new MongoDBSessionRepository(mongoTemplate);
return resp;
}
}
|
大功告成,这里只是一个简单的配置,代码也是我从项目里面节选和修改过的,至于在controller里面怎么使用,怎么做不同权限的鉴权工作那就在自己的代码里面实现就行。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://www.tianshangkun.com/2017/11/10/SpringBoot集成Shiro并用MongoDB做Session存储