资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

SpringBoot集成Shiro并利用MongoDB做Session存储的方法详解

前言

创新互联建站专注于云县企业网站建设,响应式网站建设,商城系统网站开发。云县网站建设公司,为云县等地区提供建站服务。全流程定制网站制作,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务

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.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

public class ShiroDbRealm extends AuthorizingRealm {
 /**
 * 用户信息操作
 */
 private SystemUserService systemUserService;
 public ShiroDbRealm() {}

 public ShiroDbRealm(SystemUserService systemUserService) {
 this.systemUserService = systemUserService;
 }
 /**
 * 授权信息
 */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
 SimpleAuthorizationInfo info = (SimpleAuthorizationInfo) ShiroKit.getShiroSessionAttr("perms");
 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和实现:

public interface ShiroSessionRepository {
 /**
 * 
 * @param session
 */
 void saveSession(Session session);
 ......
}

MongoDBSessionRepository.java

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

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 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

@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 filterChainDefinitionMap = new LinkedHashMap();
 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里面怎么使用,怎么做不同权限的鉴权工作那就在自己的代码里面实现就行。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对创新互联的支持。


文章题目:SpringBoot集成Shiro并利用MongoDB做Session存储的方法详解
网页地址:http://www.cdkjz.cn/article/igeoge.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220