之前项目鉴权一直使用的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里面怎么使用,怎么做不同权限的鉴权工作那就在自己的代码里面实现就行。

文章来源:

dhttp://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?tn=SpringBoot

SpringBoot集成Shiro并用MongoDB做Session存储的更多相关文章

  1. SpringBoot集成Shiro 实现动态加载权限

    一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...

  2. SpringBoot学习笔记(五):SpringBoot集成lombok工具、SpringBoot集成Shiro安全框架

    SpringBoot集成lombok工具 什么是lombok? 自动生成setget方法,构造函数,打印日志 官网:http://projectlombok.org/features/index. 平 ...

  3. springboot集成shiro实现权限认证

    github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...

  4. springboot集成shiro 实现权限控制(转)

    shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...

  5. 【Shiro】SpringBoot集成Shiro

    项目版本: springboot2.x shiro:1.3.2 Maven配置: <dependency> <groupId>org.apache.shiro</grou ...

  6. SpringBoot集成Shiro安全框架

    跟着我的步骤:先运行起来再说 Spring集成Shiro的GitHub:https://github.com/yueshutong/shiro-imooc 一:导包 <!-- Shiro安全框架 ...

  7. springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices

    springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...

  8. SpringBoot集成Shiro实现权限控制

    Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...

  9. springboot 集成shiro

    首先看下shiro configuration 的配置,重要部分用红色标出了 package cn.xiaojf.today.shiro.configuration; import at.pollux ...

随机推荐

  1. js 中的一些小技巧

    js 数字操作: 1.1 取整: 取整有很多方法如: parseInt(a,10); Math.floor(a); a>>0; ~~a; a|0; 前面2种是经常用到的,后面3中算是比较偏 ...

  2. unity爬坑记录

    这里记一下平时遇到的unity bug: unity2017最好不要在prefab上面修改它上面的组件参数 最好是拖放到场景之后修改场景内的物体组件参数 完事了apply一下删掉 不这样做的话 可能u ...

  3. linux下简洁优化部署tomcat应用

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本文是自己根据公司架构部署tomcat方法整理出来的文本 修 ...

  4. CentOS 挂载 cdrom, iso文件作为源

    在生产系统环境中的机器都没有连接互联网,因此都是使用本地源. 首先,需要将cdrom, 或 iso文件挂载到本地目录. 1.挂载光驱: 将cdrom 放入光驱. $  mkdir /media/cdr ...

  5. C/C++语言的语法基础

    数据类型指明变量或表达式的状态和行为,数据类型决定了数的取值范围和允许执行的运算符集.c++语言数据类型可以分为两大类:基本类型和引用类型.基本类型是指不能再分解的数据类型,其数据在函数的调用中是以传 ...

  6. mysql5.7中解决中文乱码的问题

    在使用mysql5.7时,会发现通过web端向数据库中写入中文后会出现乱码,但是在数据库中直接操作SQL语句插入数据后中文就显示正常,这个问题怎么解决呢?此处不对mysql的数据编码过程和原理进行讲解 ...

  7. FLEX类似谷歌地图拖拽功能

    要实现类似于谷歌地图拖拽功能,可以用s:Scroller标签来实现,代码如下: mxml: <s:Scroller width="100%" height="100 ...

  8. Asp.Net Core2.0 基于QuartzNet任务管理系统

    Quartz.NET官网地址:https://www.quartz-scheduler.net/ Quartz.NET文档地址:https://www.quartz-scheduler.net/doc ...

  9. 各种语系的unicode对应以及local编码方式

    链接:http://www.doc88.com/p-801578373970.html 一.英文 Unicode范围: 0041-005A, 0061-007A (若含数字与符号,则为0021-007 ...

  10. spring cron 定时任务

    文章首发于个人博客:https://yeyouluo.github.io 0 预备知识:cron表达式 见 <5 参考>一节. 1 环境 eclipse mars2 + Maven3.3. ...