1、acegi内置了对CAS的支持。这里的CAS是3.2。建立CAS server是一个比较简单的事情。CAS server就是一个标准的war文件,把它发布就可以运行。需要做的仅仅是调整登陆和其他一些页面。

2、先了解一下CAS如何实现SSO。
例子:原有系统A和系统B,现在在它们之间做SSO。
很显然,系统A和B都是CAS client。首先是访问系统A,干掉A的登陆页面,在A的入口判断有没有Ticket(票据),如果没有则重定向到CAS server,在CAS server提供Credential(大多数情况就是用户名和密码)。CAS server的作用非常简单:就是来验证用户密码。正确,则发送Ticket。CAS有5种Ticket,分别是TGC(通过cookie发送的 ticket),ST(Service Ticket),PGT,PGTIOU,PT。其中PGT,PGTIOU,PT属于代理ticket,这里不作讨论。

TGC和ST的关系可以打个比方:
我去中央电视塔去玩,结果景点这么近还要买两次门票,就不能搞个通票吗?于是就SSO。于是这样:我先去电视塔,门卫告诉我你不能进去要买票,于是把我送到通票售票处(CAS server)买票(登录),买吧,于是给了我两张票,注意,是两张,一张发到我手里,上面写着仅限电视塔使用(ST);靠,不是通票吗,咋仅限电视塔使用?别急,还有一张票(TGC)通过cookie发送你看不见。人家说了保证没问题,我咋办,这是人家的规矩,那就先去玩吧。出了电视塔我直扑海底世界,
门卫说要海底世界票,不会吧,我买的通票啊,门卫说不着急,又把我送回通票售票处(CAS server),通票售票处(CAS server)一看,发现我有TGC,嘿嘿,这家伙买过票了不用再买(不用再登录),于是换我一张票(ST)上面写着仅限海底世界使用,于是我就拿着这张票又去海底世界了。于是我明白了啥是SSO了,不就是把买票改成换票了吗?
比方完了,最开始的例子也就不往下继续了。需要注意的是系统A和B整合SSO需要把A、B的用户密码集中管理,你说A中我的用户名是张三,B中是李四,SSO能不能帮我自动识别,回答是不行的。 

 

 

二、acegi配置

以一个典型的web访问来说明整个过程
1、用户访问一个受acegi安全保护的页面或业务方法;
2、用户没有登陆的话显然会抛出AuthenticationException
3、配置exceptionTranslationFilter捕获这个异常重定向到CAS server登陆页面

修改applicationContext-acegi-security.xml文件

Acegi集成CAS       <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
Acegi集成CAS            
<property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
Acegi集成CAS        
</bean>
Acegi集成CAS        
Acegi集成CAS        
<bean id="casProcessingFilterEntryPoint" class="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
Acegi集成CAS            
<property name="loginUrl"><value>https://my.company.com/cas/login</value></property>
Acegi集成CAS            
<property name="serviceProperties"><ref local="serviceProperties"/></property>
Acegi集成CAS        
</bean>
Acegi集成CAS        
Acegi集成CAS        
<bean id="serviceProperties" class="org.acegisecurity.ui.cas.ServiceProperties">
Acegi集成CAS            
<property name="service"><value>https://server.company.com/myapp/j_acegi_cas_security_check</value></property>
Acegi集成CAS            
<property name="sendRenew"><value>false</value></property>
Acegi集成CAS        
</bean>

  配置casProcessingFilter来处理返回ST(和以前的authenticationProcessingFilter比较类似)

Acegi集成CAS   <bean id="casProcessingFilter" class="org.acegisecurity.ui.cas.CasProcessingFilter">
Acegi集成CAS        
<property name="authenticationManager"><ref local="authenticationManager"/></property>
Acegi集成CAS        
<property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
Acegi集成CAS        
<property name="defaultTargetUrl"><value>/</value></property>
Acegi集成CAS        
<property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
Acegi集成CAS    
</bean>

配置authenticationManager

Acegi集成CAS   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
Acegi集成CAS      
<property name="providers">
Acegi集成CAS         
<list>
Acegi集成CAS            
<ref local="casAuthenticationProvider"/>
Acegi集成CAS         
</list>
Acegi集成CAS      
</property>
Acegi集成CAS   
</bean>
Acegi集成CAS   
Acegi集成CAS  
<bean id="casAuthenticationProvider" class="org.acegisecurity.providers.cas.CasAuthenticationProvider">
Acegi集成CAS        
<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>
Acegi集成CAS        
<property name="casProxyDecider"><ref local="casProxyDecider"/></property>
Acegi集成CAS        
<property name="ticketValidator"><ref local="casProxyTicketValidator"/></property>
Acegi集成CAS        
<property name="statelessTicketCache"><ref local="statelessTicketCache"/></property>
Acegi集成CAS        
<property name="key"><value>my_password_for_this_auth_provider_only</value></property>
Acegi集成CAS    
</bean> 

具体作用的是casAuthenticationProvider,casAuthenticationProvider通过 casProxyTicketValidator来校验ST

Acegi集成CAS    <bean id="casProxyTicketValidator" class="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
Acegi集成CAS        
<property name="casValidate"><value>https://my.company.com/cas/proxyValidate</value></property>
Acegi集成CAS        
<property name="serviceProperties"><ref local="serviceProperties"/></property>
Acegi集成CAS    
</bean> 

    

 其他 

 

 需要拷贝casclient-3.2和ehcache-1.3.0.jar加入应用的lib中

以下是整个applicationContext-acegi-security.xml

 

 

 


    - A simple "base bones" Acegi Security configuration.
    -
    - The sample includes the "popular" features that people tend to use.
    - Specifically, form authentication, remember-me, and anonymous processing.
    - Other features aren't setup, as these can be added later by inserting
    - the relevant XML fragments as specified in the Reference Guide.
    -
    - To assist new users, the filters specified in the FilterChainProxy are
    - declared in the application context in the same order. Collaborators
    - required by those filters are placed at the end of the file.
    -
    - $Id: applicationContext-acegi-security.xml,v 1.3 2008/01/09 01:41:14 fdmeng Exp $
-->

<beans>

    
<bean id="filterChainProxy"
        class
="org.acegisecurity.util.FilterChainProxy">
        
<property name="filterInvocationDefinitionSource">
            
<value><![CDATA[
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /js/**=#NONE#
                /css/**=#NONE#
                /images/**=#NONE#
                /**=httpSessionContextIntegrationFilter,casProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
            
]]></value>
        
</property>
    
</bean>

    
<bean id="httpSessionContextIntegrationFilter"
        class
="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />

    
<bean id="logoutFilter"
        class
="org.acegisecurity.ui.logout.LogoutFilter">
        
<constructor-arg value="/index.jsp" />
        
<!-- URL redirected to after logout -->
        
<constructor-arg>
            
<list>
                
<ref bean="rememberMeServices" />
                
<bean
                    
class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
            
</list>
        
</constructor-arg>
    
</bean>

    
<bean id="authenticationProcessingFilter"
        class
="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
        
<property name="authenticationManager"
            ref
="authenticationManager" />
        
<property name="authenticationFailureUrl"
            value
="/acegilogin.jsp?login_error=1" />
        
<property name="defaultTargetUrl" value="/" />
        
<property name="filterProcessesUrl"
            value
="/j_acegi_security_check" />
        
<property name="rememberMeServices" ref="rememberMeServices" />
    
</bean>

    
<bean id="securityContextHolderAwareRequestFilter"
        class
="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />

    
<bean id="rememberMeProcessingFilter"
        class
="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
        
<property name="authenticationManager"
            ref
="authenticationManager" />
        
<property name="rememberMeServices" ref="rememberMeServices" />
    
</bean>

    
<bean id="anonymousProcessingFilter"
        class
="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
        
<property name="key" value="changeThis" />
        
<property name="userAttribute"
            value
="anonymousUser,ROLE_ANONYMOUS" />
    
</bean>
    
<!-- replace to cas login -->
    
<!-- bean 
        class="org.acegisecurity.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
        <bean
        class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
        <property name="loginFormUrl"
        value="/acegilogin.jsp" />
        <property name="forceHttps" value="false" />
        </bean>
        </property>
        <property name="accessDeniedHandler">
        <bean
        class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
        <property name="errorPage"
        value="/accessDenied.jsp" />
        </bean>
        </property>
        </bean>
    
-->
    
<bean id="exceptionTranslationFilter"
        class
="org.acegisecurity.ui.ExceptionTranslationFilter">
        
<property name="authenticationEntryPoint">
            
<ref local="casProcessingFilterEntryPoint" />
        
</property>
    
</bean>

    
<bean id="casProcessingFilterEntryPoint"
        class
="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
        
<property name="loginUrl">
            
<value>https://EafyYe:8443/cas-server-webapp-3.2.1.1/login</value>
        
</property>
        
<property name="serviceProperties">
            
<ref local="serviceProperties" />
        
</property>
    
</bean>

    
<bean id="serviceProperties"
        class
="org.acegisecurity.ui.cas.ServiceProperties">
        
<property name="service">
            
<value>http://www.163.com</value>
        
</property>
        
<property name="sendRenew">
            
<value>false</value>
        
</property>
    
</bean>

    
<bean id="casProcessingFilter"
        class
="org.acegisecurity.ui.cas.CasProcessingFilter">
        
<property name="authenticationManager">
            
<ref local="authenticationManager" />
        
</property>
        
<property name="authenticationFailureUrl">
            
<value>/casfailed.jsp</value>
        
</property>
        
<property name="defaultTargetUrl">
            
<value>/</value>
        
</property>
        
<property name="filterProcessesUrl">
            
<value>/j_acegi_cas_security_check</value>
        
</property>
    
</bean>

    
<bean id="authenticationManager"
        class
="org.acegisecurity.providers.ProviderManager">
        
<property name="providers">
            
<list>
                
<ref local="casAuthenticationProvider" />
            
</list>
        
</property>
    
</bean>

    
<bean id="casAuthenticationProvider"
        class
="org.acegisecurity.providers.cas.CasAuthenticationProvider">
        
<property name="casAuthoritiesPopulator">
            
<ref local="casAuthoritiesPopulator" />
        
</property>
        
<property name="casProxyDecider">
            
<ref local="rejectProxyTickets" />
        
</property>
        
<property name="ticketValidator">
            
<ref local="casProxyTicketValidator" />
        
</property>
        
<property name="statelessTicketCache">
            
<ref local="statelessTicketCache" />
        
</property>
        
<property name="key">
            
<value>my_password_for_this_auth_provider_only</value>
        
</property>
    
</bean>

    
<bean id="casAuthoritiesPopulator"
        class
="org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
        
<property name="userDetailsService" ref="inMemDaoImpl" />
    
</bean>

    
<bean id="inMemDaoImpl"
        class
="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
        
<property name="userMap">
            
<value>
                admin=password,ROLE_ADMIN
                marissa=koala,ROLE_ADMIN,ROLE_MARISSA,enabled
            
</value>
        
</property>
    
</bean>

    
<bean id="rejectProxyTickets"
        class
="org.acegisecurity.providers.cas.proxy.RejectProxyTickets" />


    
<bean id="casProxyTicketValidator"
        class
="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
        
<property name="casValidate">
            
<value>https://eafyye:8443/cas-server-webapp-3.2.1.1/serviceValidate</value>
            
<!-- https://my.company.com/cas/proxyValidate -->
        
</property>
        
<property name="serviceProperties">
            
<ref local="serviceProperties" />
        
</property>
    
</bean>

    
<bean id="statelessTicketCache"
        class
="org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache">
        
<property name="cache" ref="ticketCacheBackend" />
    
</bean>

    
<bean id="ticketCacheBackend"
        class
="org.springframework.cache.ehcache.EhCacheFactoryBean">
        
<property name="cacheManager" ref="cacheManager" />
        
<property name="cacheName" value="ticketCache" />
    
</bean>

    
<bean id="cacheManager"
        class
="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />








    
<bean id="filterInvocationInterceptor"
        class
="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
        
<property name="authenticationManager"
            ref
="authenticationManager" />
        
<property name="accessDecisionManager">
            
<bean class="org.acegisecurity.vote.AffirmativeBased">
                
<property name="allowIfAllAbstainDecisions"
                    value
="false" />
                
<property name="decisionVoters">
                    
<list>
                        
<bean class="org.acegisecurity.vote.RoleVoter" />
                        
<bean
                            
class="org.acegisecurity.vote.AuthenticatedVoter" />
                    
</list>
                
</property>
            
</bean>
        
</property>

        
<property name="objectDefinitionSource">
            
<ref bean="rolePermissionService" />
        
</property>

        
<!--
            <property name="objectDefinitionSource">
            <value><![CDATA[
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /secure/extreme/**=ROLE_SUPERVISOR
            /secure/**=IS_AUTHENTICATED_REMEMBERED
            /project/**=IS_AUTHENTICATED_REMEMBERED
            /secretary/**=ROLE_TELLER
            /**=IS_AUTHENTICATED_ANONYMOUSLY
            ]]></value>
            </property>
        
-->
    
</bean>

    
<bean id="rememberMeServices"
        class
="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        
<property name="userDetailsService" ref="userDetailsService" />
        
<property name="key" value="changeThis" />
    
</bean>

    
<!--
        <bean 
        class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
        <list>
        <ref local="daoAuthenticationProvider" />
        <bean
        class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
        <property name="key" value="changeThis" />
        </bean>
        <bean
        class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
        <property name="key" value="changeThis" />
        </bean>
        </list>
        </property>
        <property name="sessionController">
        <ref bean="concurrentSessionController" />
        </property>
        </bean>
    
-->

    
<bean id="concurrentSessionController"
        class
="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
        
<property name="maximumSessions">
            
<value>1</value>
        
</property>
        
<property name="sessionRegistry">
            
<ref local="sessionRegistry" />
        
</property>
    
</bean>

    
<bean id="sessionRegistry"
        class
="org.acegisecurity.concurrent.SessionRegistryImpl" />

    
<bean id="daoAuthenticationProvider"
        class
="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        
<property name="userDetailsService" ref="userDetailsService" />
    
</bean>

    
<!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
    
<!--
        <bean >
        <property name="userProperties">
        <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" value="classpath:users.properties"/>
        </bean>
        </property>
        </bean>
    
-->

    
<bean id="userDetailsService"
        class
="org.security.acegi.AcegiJdbcDaoImpl">
        
<property name="dataSource">
            
<ref bean="dataSource" />
        
</property>

        
<property name="usersByUsernameQuery">
            
<value>
                SELECT u.user_id, u.company_id, u.email, u.password,
                u.enabled from role r, user_role ur, user u where
                r.role_id = ur.role_id and ur.user_id = u.user_id and
                email = ? limit 1
            
</value>
        
</property>

        
<property name="authoritiesByUsernameQuery">
            
<value>
                SELECT u.email, r.role_name FROM user_role ur, user u,
                role r WHERE ur.user_id = u.user_id and ur.role_id =
                r.role_id and u.email = ?
            
</value>
        
</property>
    
</bean>

    
<bean id="rolePermissionService"
        class
="org.security.acegi.AcegiJdbcDefinitionSourceImpl">
        
<property name="dataSource">
            
<ref bean="dataSource" />
        
</property>
        
<property name="permissionsQuery">
            
<value>
                SELECT resource_name, role_name FROM resource_role rr,
                resource re, role ro WHERE rr.role_id = ro.role_id and
                rr.resource_id = re.resource_id
            
</value>
        
</property>
        
<property name="convertUrlToLowercaseBeforeComparison"
            value
="false">
        
</property>
        
<property name="resourceExpression"
            value
="PATTERN_TYPE_APACHE_ANT">
        
</property>
    
</bean>

    
<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
    
<bean id="loggerListener"
        class
="org.acegisecurity.event.authentication.LoggerListener" />

</beans>

 

参考 集成ACEGI 进行权限控制

      JA-SIG(CAS)学习笔记3

 

 

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-07-07
  • 2022-12-23
  • 2021-10-30
  • 2021-04-27
  • 2022-12-23
猜你喜欢
  • 2021-08-26
  • 2022-12-23
  • 2022-01-05
  • 2021-07-16
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案