Spring Boot集成Shiro并利用MongoDB做Session存储的方法详解
前言
shiro是一个权限框架,具体的使用可以查看其官网http://shiro.apache.org/它提供了很方便的权限认证和登录的功能.
而springboot作为一个开源框架,必然提供了和shiro整合的功能!
之前项目鉴权一直使用的Shiro,那是在SpringMVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mongodb中,这个比较符合mongodb的设计初衷,而且在分布式项目中mongodb也作为一个中间层,用来很好很方便解决分布式环境下的session同步的问题
自从SpringBoot问世之后我的项目基本上能用SpringBoot的就会用SpringBoot,用MAVEN做统一集中管理也很方便,虽然SpringBoot也提供了一套权限安全框架SpringSecurity,但是相对来说还是不是太好用,所以还是用Shiro来的方便一点,SpringBoot集成Shiro要比SpringMVC要简单的多,至少没有一堆XML配置,看起来更清爽,那么接下来我们就开始集成。
方法如下:
第一步必然是在MAVEN中先添加Shiro和mongo的依赖,我用的Shiro版本是
1.2.3
添加依赖:
org.apache.shiro shiro-core ${shiro.version} org.apache.shiro shiro-web ${shiro.version} org.apache.shiro shiro-spring ${shiro.version} org.mongodb mongo-java-driver 3.0.0 org.springframework.data spring-data-mongodb 1.7.0.RELEASE
然后在application.xml或yml中配置mongodb
spring.data.mongodb.host=127.0.0.1 spring.data.mongodb.port=27017 spring.data.mongodb.database=SHIRO_INFO
配置完成之后我们开始正式写Shiro认证的代码,先自定义一个鉴权realm,继承自AuthorizingRealm
publicclassShiroDbRealmextendsAuthorizingRealm{
/**
*用户信息操作
*/
privateSystemUserServicesystemUserService;
publicShiroDbRealm(){}
publicShiroDbRealm(SystemUserServicesystemUserService){
this.systemUserService=systemUserService;
}
/**
*授权信息
*/
@Override
protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){
SimpleAuthorizationInfoinfo=(SimpleAuthorizationInfo)ShiroKit.getShiroSessionAttr("perms");
if(null!=info&&!CollectionUtils.isEmpty(info.getRoles())
&&!CollectionUtils.isEmpty(info.getStringPermissions())){
returninfo;
}
returnnull;
}
/**
*认证信息
*/
protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthcToken)
throwsAuthenticationException{
UsernamePasswordTokentoken=(UsernamePasswordToken)authcToken;
StringuserName=token.getUsername();
if(userName!=null&&!"".equals(userName)){
SystemUserkey=newSystemUser();
key.setLoginName(token.getUsername());
key.setPassword(String.valueOf(token.getPassword()));
SystemUseruser=systemUserService.login(key);
if(user!=null){
SubjectuserTemp=SecurityUtils.getSubject();
userTemp.getSession().setAttribute("userId",user.getId());
userTemp.getSession().setAttribute("userName",user.getUserName());
returnnewSimpleAuthenticationInfo(user.getLoginName(),user.getPassword(),getName());
}
}
returnnull;
}
}
存储session进mongodb的Repository和实现:
publicinterfaceShiroSessionRepository{
/**
*
*@paramsession
*/
voidsaveSession(Sessionsession);
......
}
MongoDBSessionRepository.java
publicclassMongoDBSessionRepositoryimplementsShiroSessionRepository{
privateMongoTemplatemongoTemplate;
publicMongoDBSessionRepository(){}
publicMongoDBSessionRepository(MongoTemplatemongoTemplate){
this.mongoTemplate=mongoTemplate;
}
@Override
publicvoidsaveSession(Sessionsession){
if(session==null||session.getId()==null){
return;
}
SessionBeanbean=newSessionBean();
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
publicclassShiroSessionDAOextendsAbstractSessionDAO{
/**
*日志记录器
*/
privatestaticfinalLoggerlog=LoggerFactory.getLogger(ShiroSessionDAO.class);
/**
*数据库存储
*/
privateShiroSessionRepositoryshiroSessionRepository;
/**
*
*@return
*/
publicShiroSessionRepositorygetShiroSessionRepository(){
returnshiroSessionRepository;
}
/**
*
*@paramshiroSessionRepository
*/
publicvoidsetShiroSessionRepository(ShiroSessionRepositoryshiroSessionRepository){
this.shiroSessionRepository=shiroSessionRepository;
}
@Override
publicvoidupdate(Sessionsession)throwsUnknownSessionException{
getShiroSessionRepository().updateSession(session);
}
@Override
publicvoiddelete(Sessionsession){
if(session==null){
log.error("sessioncannotbenull,deletefailed");
return;
}
Serializableid=session.getId();
if(id!=null){
getShiroSessionRepository().deleteSession(id);
}
}
@Override
publicCollectiongetActiveSessions(){
returngetShiroSessionRepository().getAllSessions();
}
@Override
protectedSerializabledoCreate(Sessionsession){
SerializablesessionId=this.generateSessionId(session);
this.assignSessionId(session,sessionId);
getShiroSessionRepository().saveSession(session);
returnsessionId;
}
@Override
protectedSessiondoReadSession(SerializablesessionId){
returngetShiroSessionRepository().getSession(sessionId);
}
}
OK!所有基础类已经完成,最后写一个config用来全部初始化和配置Shiro
@Configuration
publicclassShiroConfig{
@Resource
privateMongoTemplatemongoTemplate;
@Resource
privateSystemUserServicesystemUserService;//这是用来判断用户名和密码的service
@Bean
publicShiroFilterFactoryBeanshiroFilter(DefaultWebSecurityManagersecurityManager){
ShiroFilterFactoryBeanshiroFilterFactoryBean=newShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
//拦截器.
MapfilterChainDefinitionMap=newLinkedHashMap();
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);
returnshiroFilterFactoryBean;
}
publicAuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor(
DefaultWebSecurityManagersecurityManager){
AuthorizationAttributeSourceAdvisoradv=newAuthorizationAttributeSourceAdvisor();
adv.setSecurityManager(securityManager);
returnadv;
}
@Bean
publicDefaultWebSecurityManagersecurityManager(DefaultWebSessionManagersessionManager,
ShiroDbRealmmyShiroRealm){
DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager();
//设置realm.
securityManager.setRealm(myShiroRealm);
securityManager.setSessionManager(sessionManager);
returnsecurityManager;
}
/**
*身份认证realm;(这里传递systemUserService给自定义的ShiroDbRealm初始化)
*
*@return
*/
@Bean
publicShiroDbRealmmyShiroRealm(){
ShiroDbRealmmyShiroRealm=newShiroDbRealm(systemUserService);
returnmyShiroRealm;
}
@Bean
publicDefaultWebSessionManagersessionManager(ShiroSessionDAOshiroSessionDao){
DefaultWebSessionManagersessionManager=newDefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(1800000l);
sessionManager.setDeleteInvalidSessions(true);sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionDAO(shiroSessionDao);
sessionManager.setSessionIdCookieEnabled(true);
SimpleCookiecookie=newSimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setHttpOnly(true);
cookie.setMaxAge(1800000);
sessionManager.setSessionIdCookie(cookie);
returnsessionManager;
}
@Bean
publicShiroSessionDAOshiroSessionDao(MongoDBSessionRepositoryshiroSessionRepository){
ShiroSessionDAOdao=newShiroSessionDAO();
dao.setShiroSessionRepository(shiroSessionRepository);
returndao;
}
@Bean
MongoDBSessionRepositoryshiroSessionRepository(){
MongoDBSessionRepositoryresp=newMongoDBSessionRepository(mongoTemplate);
returnresp;
}
}
大功告成,这里只是一个简单的配置,代码也是我从项目里面节选和修改过的,至于在controller里面怎么使用,怎么做不同权限的鉴权工作那就在自己的代码里面实现就行。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。