您现在的位置是:首页 > 文章详情

SpringBoot集成Shiro并用MongoDB做Session存储[转]

日期:2018-11-29点击:583

之前项目鉴权一直使用的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版本是

<shiro.version>1.2.3</shiro.version>

添加依赖:

<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

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

@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%E9%9B%86%E6%88%90Shiro%E5%B9%B6%E7%94%A8MongoDB%E5%81%9ASession%E5%AD%98%E5%82%A8/

原文链接:https://blog.roncoo.com/article/131564
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章