https+shiro+cas+springmvc

来源:互联网 发布:喵社交软件 编辑:程序博客网 时间:2024/05/18 08:30

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运行流程
1.当用户在casserver上验证通过后会返回本地应用,根据本地应用login链接进入login方法,该方法体内会获取用户的相关信息,根据shiro框架获取的主体的
login方法进入shiro的核心控制器Realm里进行验证,验证通过后即重定向到getProjects()方法进入项目。
2.Shiro的授权方法并不会在登录的时候就加载,而是在页面或者某些方法里使用了与权限相关的标签或者注解时才会被调用,本项目内的验证是基于Rest服务,
返回权限的集合,shiro会主动返回一个SimpleAuthorizationInfo类型的信息供其他地方验证
 
五.问题解决记录
1.开始对cas这一块不熟悉,在项目启动时候一直出现Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target异常,后来经过JIM的提醒,意识到改了casserver的地址但是没有改证书,所以要保证
证书(.cer文件)、keystore文件、server地址完全一致;
2.项目环境搭建起来后,出现Error creating bean with name 'projectServiceImpl': Bean with name 'projectServiceImpl' has been injected into other beans
[projectSnapshotServiceImpl,templateProjectServiceImpl] in its raw version as part of a circular reference, but has eventually
been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of
over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example. 发现
在项目里出现了好几处Service相互调用Service(其实最后还是要调用dao,一般思路都是Service直接调用dao)的情况,造成了循环引用抛出异常,把相关的
地方修改了就恢复正常了;
3.在进行”Open Project”等操作时出现org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : 
[com.xxx.h5designer.po.Tproject.tbizparamters#2]异常,要将一些save和update方法改为merge;
4.调用接口问题(授权过程,例如前端加个shiro标签验证权限的时候),由于本项目的用户信息都是基于rest服务在杭州获取到的,由于开始提供的appId在两边
没有完成对接,一直没有发现问题(500 Internal Server Error)的原因,就试着将appId由2改为1才发现问题根源,可以在浏览器内输入接口地址和相关参
数模拟查看。
六.遗留问题和后续工作

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 进程号


这是最近做项目的一点经验,有很多理解不透彻的地方欢迎指正,在配置文件那一块有部分是用自定义的,所以需要的可以查看其它博主写的相关内容

0 0
原创粉丝点击