Shiro+cas实现单点登录及权限控制
一.首先配置web.xml
<!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置。-->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<!-- 配置登录过滤器,主要负责在登录时重定到服务器页面 -->
<filter-name>CAS Authentication Filter</filter-name>
<filter-class>com.xxx.h5designer.filter.H5AuthenticationFilter</filter-class>
<init-param>
<!-- 到服务器地址,注意后面的/login -->
<param-name>casServerLoginUrl</param-name>
<param-value>https://xxx.xxx.com:8443/cas/login</param-value>
</init-param>
<init-param>
<!-- 本程序所在的URL -->
<param-name>service</param-name>
<param-value>https://localhost:8444/H5UIDesigner</param-value>
</init-param>
<init-param>
<param-name>excludeUrl</param-name>
<param-value>/*.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<!-- 要求登录时的链接 -->
<param-value>https://xxx.xxx.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>service</param-name>
<!-- 本 -->
<param-value>https://localhost:8444/H5UIDesigner</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责实现HttpServletRequest请求的包裹,
比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
比如AssertionHolder.getAssertion().getPrincipal().getName()。-->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Shiro -->
<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>
二.增加shiro配置文件
<context:component-scan base-package="com.xxx.h5designer.security"></context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- shiro的核心安全接口 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接, service后是登录成功后的地址 -->
<property name="loginUrl" value="https://xxx.xxx.com:8443/cas/login?service=https://localhost:8444/H5UIDesigner" />
<property name="filters">
<util:map>
<!-- 添加casFilter到shiroFilter -->
<entry key="casFilter" value-ref="casFilter"/>
</util:map>
</property>
<!-- 自定义的权限过滤器 -->
<property name="filterChainDefinitions">
<value>
/*.jsp = anon
/H5UIDesigner* = casFilter
/logout = logoutFilter
</value>
</property>
</bean>
<bean id="casFilter" class="com.xxx.h5designer.security.H5CasFilter">
<!-- 配置验证错误时的失败页面,(Ticket 校验不通过时展示的错误页面) -->
<property name="failureUrl" value="/error.jsp"/>
</bean>
<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="https://xxx.xxx.com:8443/cas/logout?service=https://localhost:8444/H5UIDesigner" />
</bean>
<!-- 此处的Realm可以试用shiro工具类里的 -->
<bean id="casRealm" class="com.xxx.h5designer.security.H5CasRealm"></bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="casRealm"/>
<property name="subjectFactory" ref="casSubjectFactory"/>
</bean>
<!-- 如果要实现cas的remember me的功能,需要用到下面这个bean,并设置到securityManager的subjectFactory中 -->
<bean id="casSubjectFactory" class="com.xxx.h5designer.security.H5CasSubjectFactory"/>
<!--保证实现了Shiro内部lifecycle函数的bean执行, 开启注解?? -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
三.在springmvc的配置文件里增加下面配置
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
返回权限的集合,shiro会主动返回一个 SimpleAuthorizationInfo类型的信息供其他地方验证
1.在单点登录验证通过跳转到本地项目时,控制台会打印一条Info级别的消息:INFO ProxyGrantingTicketStorageImpl:88 - org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl(org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl.retrieve(ProxyGrantingTicketStorageImpl.java:88)) | No Proxy Ticket found for [].目前还不太明白这条日志的含义,应该是跟cas相关的;
七.Cas服务若部署到服务器必须要域名才能够实现(本地除外)
部署H5(cas)到Linux服务器实验步骤(注意路径的双、引号斜杠和反斜杠):
https协议、证书的生成和导入:
1. keytool -v -genkey -alias caspax -keyalg RSA -keysize 1024 -keypass 123456 -keystore /usr/local/tomcat/keystore/caspax.keystore -storepass 123456 -validity 3600
由于我们的H5验证的cas服务由公司的研发中心提供,所以不需要执行此步骤2,直接进行步骤3
2. keytool -export -alias caspax -file /usr/local/keystore/caspax.cer -keystore /usr/local/tomcat/keystore/caspax.keystore -storepass 123456
3. keytool -import -trustcacerts -alias caspax -keystore $JAVA_HOME\jre\lib\security\cacerts -file /usr/local/tomcat/keystore/caspax.cer -storepass 123456
前面三步一般不会出现问题,有问题的话一般是因为路径格式不对, 此处可能提示password was incorrect,将123456改为changeit
4. 修改本地host文件映射
5. 修改server.xml
①(添加节点)<Connector port="8444" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="/usr/local/keystore/localhost.keystore" keystorePass="123456" clientAuth="false" sslProtocol="TLS" />
②.(修改节点:name值)<Host appBase="webapps" autoDeploy="true" name="h5.xxx.com" unpackWARs="true">
6.修改web.xml,spring-shiro.xml里localhost为域名
keytool生成根证书时出现如下错误:
keytool错误:java.io.IOException:keystore was tampered with,or password was incorrect
原因是在你的home目录下是否还有.keystore存在。如果存在那么把他删除掉,后再执行
或者删除$JAVA_HOME/jre/lib/security/cacerts 再执行
也可能是密码错误,默认密码为changeit
-------------------------
1. 查看tomcat状态: ps -ef|grep java
2. 停止tomcat:./shutdown.sh,若停止失败采取强制关闭:kill -9 进程号
这是最近做项目的一点经验,有很多理解不透彻的地方欢迎指正,在配置文件那一块有部分是用自定义的,所以需要的可以查看其它博主写的相关内容