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

网友投稿 376 2023-03-05


Spring Boot集成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来http://的方便一点,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里面怎么使用,怎么做不同权限的鉴权工作那就在自己的代码里面实现就行。

总结

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:vue给input file绑定函数获取当前上传的对象完美实现方法
下一篇:详解最新vue
相关文章

 发表评论

暂时没有评论,来抢沙发吧~