一、前言
Apache Shiro与Spring Security一样是Java的一个安全框架。那为什么与Spring整合却用Shiro?不要问为什么,任性!开个玩笑:D 其实我个人是认为Spring Security太过于笨重,要写太多的过滤器。我是个怕麻烦的人,Shiro的配置简单这就是我选择的理由,何况Spring官方自己都推荐使用Shiro。而Shiro权限控制与CAS单点登录的组合更是堪称Java安全中的***~( ̄_, ̄ )……但本文只介绍它们三者的整合配置(说白了就是给自己留个学习笔记啦),若对此方面内容感兴趣的可以到网上搜索学习,在此推荐开涛大神的:《跟我学shiro》。
再次强调,以下内容仅为个人学习笔记,不是篇教程。
二、配置
Shiro最主要的就是认证与授权,而CAS的重点在于单点登录,其实CAS与Shiro整合的话就是关于认证那块的整合。
我们先来看web.xml中Shiro与CAS的配置:
<!-- 引入详情配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/cas-client-shiro.xml </param-value> </context-param> <!-- shiro配置 (需写在Spring MVC Servlet配置之前)--> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> spring mvc servlet配置…… <!-- 退出 --> <filter> <filter-name>logoutFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>logoutFilter</filter-name> <url-pattern>/logout</url-pattern> </filter-mapping> <!-- 该过滤器用于实现单点登出功能,可选配置。--> <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>singleSignOutFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ………………其它配置省略………………
在上面的配置中是否有留意到这货:DelegatingFilterProxy,它会自动的把filter请求交给相应名称的bean处理。例如在启动时,spring会有一个filter请求,这个请求转交给了shiroFilter这个bean去处理了。so^接下来我们就得去找找看shiroFilter在哪?
此为上文加载的cas-client-shiro.xml配置:
<!-- shiro配置 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<!-- 设定角色的登录链接,这里为cas登录页面的链接和可配置回调地址 -->
<property name="loginUrl" value="${cas.casServerLoginUrl}?service=${cas.service}login/" />
<property name="successUrl" value="/" />
<property name="filters">
<util:map>
<!-- 添加casFilter到shiroFilter整合 -->
<entry key="casFilter" value-ref="casFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login/ = casFilter
/logout = anon
/** = authc
</value>
</property>
</bean>
<!-- CasFilter为自定义的单点登录Fileter -->
<bean id="casFilter" class="com.test.shiro.filter.CasFilter">
<!-- 配置验证错误时的失败页面 -->
<property name="failureUrl" value="${cas.casServerLogoutUrl}?service=${cas.logoutRedirectUrl}"/>
<property name="realm" ref="casRealm"/>
</bean>
<!-- MyRealm为自定义的Realm -->
<bean id="casRealm" class="com.test.shiro.realm.MyRealm">
<property name="cacheManager" ref="shiroMemcacheManager" />
<property name="appId" value="${roomy.uap.client.appId}"/>
<property name="casServerUrlPrefix" value="${cas.host}"/>
<!-- 客户端的回调地址设置 -->
<property name="casService" value="${cas.service}login/"/>
</bean>
<!-- 缓存管理器 -->
………………
<!-- 会话sessionDAO -->
………………
<!-- 会话管理器sessionManager -->
………………
<!-- 会话验证调度器sessionValidationScheduler -->
………………
<!-- 安全管理器securityManager -->
………………
<!-- Shiro生命周期处理器lifecycleBeanPostProcessor-->
………………
<!-- 退出 -->
<bean name="logoutFilter" class="com.test.cas.client.filter.LogoutFilterWithShiro">
<property name="casServerLogoutUrl" value="${cas.casServerLogoutUrl}"></property>
<property name="redirectUrl" value="${cas.logoutRedirectUrl}"></property>
</bean>
<!-- 单点登出 -->
<bean name="singleSignOutFilter"
class="com.test.cas.client.session.SingleSignOutFilter">
<property name="sessionMappingStorage" ref="sessionMappingStorage">
</property>
</bean>
<bean id="sessionMappingStorage" class="com.test.cas.client.session.ShiroBackedSessionMappingStorage">
<property name="cacheManager" ref="shiroMemcacheManager" />
<property name="sessionManager" ref="sessionManager" />
</bean>以上内容众多省略,其实我想强调的是MyRealm。恩,我们要实现的认证、预授权操作都在此自定义的Realm中实现操作。MyRealm继承了CasRealm,CasRealm又继承了AuthorizingRealm。所以,MyRealm中具体写了授权实现逻辑,而认证则调用了CasRealm中的方法……
三、结语
为什么不好好的写一篇博文教程?首先,这方面的东西内容非常多,不是一两篇能说的清楚的。其次,自己也是刚开始学习,并未完全掌握。最后,本人特别懒,目前只是想给自己留个学习笔记而已。
本文出自 “学而思” 博客,请务必保留此出处http://linhongyu.blog.51cto.com/6373370/1587818
原文地址:http://linhongyu.blog.51cto.com/6373370/1587818