SpringBoot集成Shiro并用MongoDB做Session存储
之前项目鉴权一直使用的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存储的更多相关文章
- SpringBoot集成Shiro 实现动态加载权限
一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...
- SpringBoot学习笔记(五):SpringBoot集成lombok工具、SpringBoot集成Shiro安全框架
SpringBoot集成lombok工具 什么是lombok? 自动生成setget方法,构造函数,打印日志 官网:http://projectlombok.org/features/index. 平 ...
- springboot集成shiro实现权限认证
github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...
- springboot集成shiro 实现权限控制(转)
shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...
- 【Shiro】SpringBoot集成Shiro
项目版本: springboot2.x shiro:1.3.2 Maven配置: <dependency> <groupId>org.apache.shiro</grou ...
- SpringBoot集成Shiro安全框架
跟着我的步骤:先运行起来再说 Spring集成Shiro的GitHub:https://github.com/yueshutong/shiro-imooc 一:导包 <!-- Shiro安全框架 ...
- springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices
springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...
- SpringBoot集成Shiro实现权限控制
Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...
- springboot 集成shiro
首先看下shiro configuration 的配置,重要部分用红色标出了 package cn.xiaojf.today.shiro.configuration; import at.pollux ...
随机推荐
- MongoDB之分片集群(Sharding)
MongoDB之分片集群(Sharding) 一.基本概念 分片(sharding)是一个通过多台机器分配数据的方法.MongoDB使用分片支持大数据集和高吞吐量的操作.大数据集和高吞吐量的数据库系统 ...
- S5PV210中断处理
_start: 1.设置栈空间:防止之前的UBOOT代码被覆盖,应为c中需要栈空间 ldr sp, =0x40010000 2.设置CPSR的I,F位,A8打开IRQ,FIQ中断: mov r0, # ...
- 在一台电脑上运行两个或两个以上的tomcat
前言 在开发过程中,我们可能会同时用到多个tomcat,但以正常安装的形式安装多个tomcat,无论启动哪一个tomcat,打开的都是配置了环境变量的那一个tomcat,所以进行一些设置,以达到我们同 ...
- Selenium常用API用法示例集----下拉框、文本域及富文本框、弹窗、JS、frame、文件上传和下载
元素识别方法.一组元素定位.鼠标操作.多窗口处理.下拉框.文本域及富文本框.弹窗.JS.frame.文件上传和下载 元素识别方法: driver.find_element_by_id() driver ...
- Shiro 核心功能案例讲解 基于SpringBoot 有源码
Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...
- ubuntu16.04~qt 5.8无法输入中文
编译fcitx-qt需要cmake,安装cmake命令,如果已经安装,请略过. sudo apt-get install cmake 安装 fcitx-libs-dev sudo apt-get in ...
- HDU - 1495 bfs [kuangbin带你飞]专题一
模拟倒水的过程,每次可以把第i个杯子的水向第j个杯子里面倒,这可能出现新的状态,不停的更新状态,指导某两个杯子的水等于S/2说明找到答案,如果所有状态搜索完毕仍然不能均分,则退出. 注意:如果S是奇数 ...
- 在SpringBoot中存放session到Redis
前言 今天你们将再一次领略到SpringBoot的开发到底有多快,以及SpringBoot的思想(默认配置) 我们将使用redis存放用户的session,用户session存放策略有很多,有存放到内 ...
- JAVA 处理 Spring data mongodb 时区问题
Spring data mongodb 查询出结果的时候会自动 + 8小时,所以我们看起来结果是对的 但是我们查询的时候,并不会自动 + 8小时,需要自己处理 解决方法 1 @JsonFormat ...
- SpaceNet数据集
SpaceNet数据集 SpaceNet是DigitalGlobe商业卫星公司提供的遥感图像集合,包含一些标记信息可用作机器学习研究. SpaceNet Challenge主页: https://sp ...