欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-20 11:50:46
前言 shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能. 而springboo...

前言

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

总结

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