详解Spring Boot 集成Shiro和CAS
程序员文章站
2024-02-23 13:12:22
请大家在看本文之前,先了解如下知识点:
1、shiro 是什么?怎么用?
2、cas 是什么?怎么用?
3、最好有spring基础
首先看一下...
请大家在看本文之前,先了解如下知识点:
1、shiro 是什么?怎么用?
2、cas 是什么?怎么用?
3、最好有spring基础
首先看一下下面这张图:
第一个流程是单纯使用shiro的流程。
第二个流程是单纯使用cas的流程。
第三个图是shiro集成cas后的流程。
ps:流程图急急忙忙画的,整体上应该没有什么问题,具体细节问题还请大家留言指正。
如果你只是打算用到你的spring boot项目中,那么看着如下配置完成便可。
如果你想进一步了解其中的细节,还是建议大家单独配置shiro、单独配置cas,看看官方相关文档。
shiro在1.2版本开始提供了对cas的集成,按下面添加依赖到pom.xml中:
<!--apache shiro所需的jar包 --> <dependency> <groupid>org.apache.shiro</groupid> <artifactid>shiro-spring</artifactid> <version>1.2.4</version> </dependency> <dependency> <groupid>org.apache.shiro</groupid> <artifactid>shiro-ehcache</artifactid> <version>1.2.4</version> </dependency> <dependency> <groupid>org.apache.shiro</groupid> <artifactid>shiro-cas</artifactid> <version>1.2.4</version> </dependency>
shiro-cas 依赖 shiro-web,shiro-web 依赖 shiro-core,所以添加shiro-cas后shiro-web.jar和shiro-core.jar会自动被引用。
cas被shiro集成后,其原理就是shiro将casfilter加入到shirofilter的filterchain中。
在springboot工程中创建shirocasconfiguration.java
package org.springboot.sample.config; import java.util.hashmap; import java.util.linkedhashmap; import java.util.map; import javax.servlet.filter; import org.apache.shiro.cache.ehcache.ehcachemanager; import org.apache.shiro.cas.casfilter; import org.apache.shiro.cas.cassubjectfactory; import org.apache.shiro.spring.lifecyclebeanpostprocessor; import org.apache.shiro.spring.security.interceptor.authorizationattributesourceadvisor; import org.apache.shiro.spring.web.shirofilterfactorybean; import org.apache.shiro.web.mgt.defaultwebsecuritymanager; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springboot.sample.dao.iscoredao; import org.springboot.sample.security.myshirocasrealm; import org.springboot.sample.service.studentservice; import org.springframework.aop.framework.autoproxy.defaultadvisorautoproxycreator; import org.springframework.boot.context.embedded.filterregistrationbean; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.web.filter.delegatingfilterproxy; /** * shiro集成cas配置 * * @author 单红宇(365384722) * @create 2016年1月17日 */ @configuration public class shirocasconfiguration { private static final logger logger = loggerfactory.getlogger(shirocasconfiguration.class); // casserverurlprefix public static final string casserverurlprefix = "https://localhost:8443/cas"; // cas登录页面地址 public static final string casloginurl = casserverurlprefix + "/login"; // cas登出页面地址 public static final string caslogouturl = casserverurlprefix + "/logout"; // 当前工程对外提供的服务地址 public static final string shiroserverurlprefix = "http://localhost:9090/myspringboot"; // casfilter urlpattern public static final string casfilterurlpattern = "/shiro-cas"; // 登录地址 public static final string loginurl = casloginurl + "?service=" + shiroserverurlprefix + casfilterurlpattern; @bean public ehcachemanager getehcachemanager() { ehcachemanager em = new ehcachemanager(); em.setcachemanagerconfigfile("classpath:ehcache-shiro.xml"); return em; } @bean(name = "myshirocasrealm") public myshirocasrealm myshirocasrealm(ehcachemanager cachemanager) { myshirocasrealm realm = new myshirocasrealm(); realm.setcachemanager(cachemanager); return realm; } /** * 注册delegatingfilterproxy(shiro) * * @param dispatcherservlet * @return * @author shanhy * @create 2016年1月13日 */ @bean public filterregistrationbean filterregistrationbean() { filterregistrationbean filterregistration = new filterregistrationbean(); filterregistration.setfilter(new delegatingfilterproxy("shirofilter")); // 该值缺省为false,表示生命周期由springapplicationcontext管理,设置为true则表示由servletcontainer管理 filterregistration.addinitparameter("targetfilterlifecycle", "true"); filterregistration.setenabled(true); filterregistration.addurlpatterns("/*"); return filterregistration; } @bean(name = "lifecyclebeanpostprocessor") public lifecyclebeanpostprocessor getlifecyclebeanpostprocessor() { return new lifecyclebeanpostprocessor(); } @bean public defaultadvisorautoproxycreator getdefaultadvisorautoproxycreator() { defaultadvisorautoproxycreator daap = new defaultadvisorautoproxycreator(); daap.setproxytargetclass(true); return daap; } @bean(name = "securitymanager") public defaultwebsecuritymanager getdefaultwebsecuritymanager(myshirocasrealm myshirocasrealm) { defaultwebsecuritymanager dwsm = new defaultwebsecuritymanager(); dwsm.setrealm(myshirocasrealm); // <!-- 用户授权/认证信息cache, 采用ehcache 缓存 --> dwsm.setcachemanager(getehcachemanager()); // 指定 subjectfactory dwsm.setsubjectfactory(new cassubjectfactory()); return dwsm; } @bean public authorizationattributesourceadvisor getauthorizationattributesourceadvisor(defaultwebsecuritymanager securitymanager) { authorizationattributesourceadvisor aasa = new authorizationattributesourceadvisor(); aasa.setsecuritymanager(securitymanager); return aasa; } /** * 加载shirofilter权限控制规则(从数据库读取然后配置) * * @author shanhy * @create 2016年1月14日 */ private void loadshirofilterchain(shirofilterfactorybean shirofilterfactorybean, studentservice stuservice, iscoredao scoredao){ /////////////////////// 下面这些规则配置最好配置到配置文件中 /////////////////////// map<string, string> filterchaindefinitionmap = new linkedhashmap<string, string>(); filterchaindefinitionmap.put(casfilterurlpattern, "casfilter");// shiro集成cas后,首先添加该规则 // authc:该过滤器下的页面必须验证后才能访问,它是shiro内置的一个拦截器org.apache.shiro.web.filter.authc.formauthenticationfilter filterchaindefinitionmap.put("/user", "authc");// 这里为了测试,只限制/user,实际开发中请修改为具体拦截的请求规则 // anon:它对应的过滤器里面是空的,什么都没做 logger.info("##################从数据库读取权限规则,加载到shirofilter中##################"); filterchaindefinitionmap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取 filterchaindefinitionmap.put("/login", "anon"); filterchaindefinitionmap.put("/**", "anon");//anon 可以理解为不拦截 shirofilterfactorybean.setfilterchaindefinitionmap(filterchaindefinitionmap); } /** * cas过滤器 * * @return * @author shanhy * @create 2016年1月17日 */ @bean(name = "casfilter") public casfilter getcasfilter() { casfilter casfilter = new casfilter(); casfilter.setname("casfilter"); casfilter.setenabled(true); // 登录失败后跳转的url,也就是 shiro 执行 casrealm 的 dogetauthenticationinfo 方法向casserver验证tiket casfilter.setfailureurl(loginurl);// 我们选择认证失败后再打开登录页面 return casfilter; } /** * shirofilter<br/> * 注意这里参数中的 studentservice 和 iscoredao 只是一个例子,因为我们在这里可以用这样的方式获取到相关访问数据库的对象, * 然后读取数据库相关配置,配置到 shirofilterfactorybean 的访问规则中。实际项目中,请使用自己的service来处理业务逻辑。 * * @param myshirocasrealm * @param stuservice * @param scoredao * @return * @author shanhy * @create 2016年1月14日 */ @bean(name = "shirofilter") public shirofilterfactorybean getshirofilterfactorybean(defaultwebsecuritymanager securitymanager, casfilter casfilter, studentservice stuservice, iscoredao scoredao) { shirofilterfactorybean shirofilterfactorybean = new shirofilterfactorybean(); // 必须设置 securitymanager shirofilterfactorybean.setsecuritymanager(securitymanager); // 如果不设置默认会自动寻找web工程根目录下的"/login.jsp"页面 shirofilterfactorybean.setloginurl(loginurl); // 登录成功后要跳转的连接 shirofilterfactorybean.setsuccessurl("/user"); shirofilterfactorybean.setunauthorizedurl("/403"); // 添加casfilter到shirofilter中 map<string, filter> filters = new hashmap<>(); filters.put("casfilter", casfilter); shirofilterfactorybean.setfilters(filters); loadshirofilterchain(shirofilterfactorybean, stuservice, scoredao); return shirofilterfactorybean; } }
创建权限认证的 myshirocasrealm.java
package org.springboot.sample.security; import java.util.list; import javax.annotation.postconstruct; import org.apache.shiro.authz.authorizationinfo; import org.apache.shiro.authz.simpleauthorizationinfo; import org.apache.shiro.cas.casrealm; import org.apache.shiro.subject.principalcollection; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springboot.sample.config.shirocasconfiguration; import org.springboot.sample.dao.iuserdao; import org.springboot.sample.entity.role; import org.springboot.sample.entity.user; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; import org.springframework.transaction.annotation.transactional; public class myshirocasrealm extends casrealm{ private static final logger logger = loggerfactory.getlogger(myshirocasrealm.class); @autowired private iuserdao userdao; @postconstruct public void initproperty(){ // setdefaultroles("role_user"); setcasserverurlprefix(shirocasconfiguration.casserverurlprefix); // 客户端回调地址 setcasservice(shirocasconfiguration.shiroserverurlprefix + shirocasconfiguration.casfilterurlpattern); } /** * 权限认证,为当前登录的subject授予角色和权限 * @see 经测试:本例中该方法的调用时机为需授权资源被访问时 * @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用authorizationcache * @see 经测试:如果连续访问同一个url(比如刷新),该方法不会被重复调用,shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行 */ @override protected authorizationinfo dogetauthorizationinfo(principalcollection principalcollection) { logger.info("##################执行shiro权限认证##################"); //获取当前登录输入的用户名,等价于(string) principalcollection.fromrealm(getname()).iterator().next(); string loginname = (string)super.getavailableprincipal(principalcollection); //到数据库查是否有此对象 user user=userdao.findbyname(loginname);// 实际项目中,这里可以根据实际情况做缓存,如果不做,shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 if(user!=null){ //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission) simpleauthorizationinfo info=new simpleauthorizationinfo(); //用户的角色集合 info.setroles(user.getrolesname()); //用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的四行可以不要 list<role> rolelist=user.getrolelist(); for (role role : rolelist) { info.addstringpermissions(role.getpermissionsname()); } // 或者按下面这样添加 //添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色 // simpleauthorinfo.addrole("admin"); //添加权限 // simpleauthorinfo.addstringpermission("admin:manage"); // logger.info("已为用户[mike]赋予了[admin]角色和[admin:manage]权限"); return info; } // 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedurl指定的地址 return null; } } 在controller中添加一个方法,用于将登录url简单化,提供一个重定向功能 @requestmapping(value="/login",method=requestmethod.get) public string loginform(model model){ model.addattribute("user", new user()); // return "login"; return "redirect:" + shirocasconfiguration.loginurl; }
本文主要是介绍如何在spring boot中集成shiro+cas,并非一个从零创建工程到整体完成的介绍。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
详解Spring Boot 集成Shiro和CAS
-
详解spring Boot Cli的配置和使用
-
详解Spring Boot微服务如何集成fescar解决分布式事务问题
-
详解Spring Boot微服务如何集成fescar解决分布式事务问题
-
Spring Boot Redis 集成配置详解
-
详解Spring Boot集成MyBatis(注解方式)
-
详解Spring Boot 使用Spring security 集成CAS
-
Spring Boot集成Shiro并利用MongoDB做Session存储的方法详解
-
spring boot整合CAS配置详解
-
详解Spring Boot 集成Shiro和CAS