SpringBoot集成Shiro并用MongoDB做Session存储

来源:互联网 发布:bilibili for mac发热 编辑:程序博客网 时间:2024/06/06 18:08

之前项目鉴权一直使用的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.1spring.data.mongodb.port=27017spring.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

@Configurationpublic 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/


更多参考内容请登录:http://www.roncoo.com/article/index





阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刘伶醉头曲 刘伶醉38度 一号刘伶醉 刘伶醉香型 刘伶醉38度多少钱 刘伶醉天润 刘伶醉醉9 刘伶醉价格表 刘伶醉老酒价格表 刘伶醉纯6 刘伶醉杨子 刘伶醉二十年 刘伶醉厂址 刘伶醉 七贤 刘伶醉老窖酒 刘伶醉专卖店 刘伶醉42度 杜康刘伶醉 刘伶醉纯3价格 刘伶醉52度 刘伶醉十三年 刘伶醉二号价格 刘伶醉窖储十五年 刘伶醉谁代言的 刘伶醉地润价格 刘伶醉的产地 刘伶醉地润 刘伶醉42度价格 52度刘伶醉 刘伶醉6纯价格 刘伶醉度数 刘伶醉窖储十年 刘伶醉6年 刘伶醉门头 刘伶醉水润 刘伶醉润酒价格 刘伶醉红瓶 刘伶醉地润酒价格 刘伶醉30年 刘伶醉logo 刘伶醉窖储十二年