前言
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存儲