CAS Spring Security 3 整合配置

 通常來講, Web 應用的安全性包括用戶認證( Authentication )和用戶受權( Authorization )兩個部分。用戶認證指的是驗證某個用戶是否爲系統中的合法主體,也就是說用戶可否訪問該系統。用戶受權指的是驗證某個用戶是否有權限執行某個操做。在一個系統中,不一樣用戶所具備的權限是不一樣的。好比對一個文件來講,有的用戶只能進行讀取,而有的用戶能夠進行修改。通常來講,系統會爲不一樣的用戶分配不一樣的角色,而每一個角色則對應一系列的權限。java

  對於上面提到的兩種應用情景, Spring Security 框架都有很好的支持。在用戶認證方面, Spring Security 框架支持主流的認證方式,包括 HTTP 基本認證、 HTTP 表單驗證、 HTTP 摘要認證、 OpenID  LDAP 等。在用戶受權方面, Spring Security 提供了基於角色的訪問控制和訪問控制列表( Access Control List  ACL ),能夠對應用中的領域對象進行細粒度的控制。mysql

 Spring Security 整合 CAS 單點登陸  使用 CAS 進行認證和獲取受權信息  使用 Spring Security 驗證權限 ,則能夠很好的把公共的認證和受權與具體應用剝離開來,同時簡化應用的配置。本文就 Spring Security  CAS 的整合進行說明。web

一 、基本需求 
1. jdk 5.0 
2. tomcat 6 
3. Spring 3.0.5.RELEASE 
4. Spring Security 3.1.0.RELEASE 
5. CAS cas-server-3.4.7, cas-client-3.2.0 
6. 使用http協議進行傳輸 
7. 經過jdbc進行用戶驗證,須要經過casserver提供除登陸用戶名之外的附加信息(用於Spring Security 進行驗證權限) 
2、搭建CAS Server 
1. 把從 http://www.jasig.org/cas/download 上下載cas解壓找到 cas-server-3.4.7-releasecas-server-3.4.7modulescas-server-webapp-3.4.7.war , 解壓cas-server-webapp-3.4.7.war ,部署在至tomcat上端口爲 8080的server上,如部署路徑爲 http://localhost:8080/cas 。爲了達到需求目的,咱們主要須要對 /WEB-INF/deployerConfigContext.xml 文件進行修改。
spring

2. 使用 jdbc 數據源進行用戶認證,須要修改 deployerConfigContext.xml  authenticationHandlers 方式 
<property name=" 
authenticationHandlers "> 
<list> 
<!-- 
| This is the authentication handler that authenticates services by means of callback via SSL, thereby validating 
| a server side SSL certificate. 
+--> 
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" 
p:httpClient-ref="httpClient" /> 
<!-- 
| This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS  
| into production. The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials 
| where the username equals the password. You will need to replace this with an AuthenticationHandler that implements your 
| local authentication strategy. You might accomplish this by coding a new such handler and declaring 
| edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules. 
+--> 
// 
註釋掉,不然只要用戶名和密碼一致的話均可以獲得認證   
<!-- bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" / --> 

// 
數據庫認證方式 
<!--DATABASE -- > 
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" /> 
<property name="sql" value="select password from t_admin_user where login_name=?" /> 
</bean> 

</list> 
<property name="authenticationHandlers">
sql

<!-- DATABASE 增長數據源配置 --> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property> 
<property name="url"><value>jdbc:mysql:///cas?useUnicode=true&amp;characterEncoding=utf-8</value></property> 
<property name="username"><value>root</value></property> 
</bean>
數據庫

3. 經過 casserver 提供除登陸用戶名之外的附加信息(用於 Spring Security 進行驗證權限),修改 /WEB-INF/ deployerConfigContext .xml 
3.1 
修改 credentialsToPrincipalResolvers 
<property name="credentialsToPrincipalResolvers"> 
<list> 
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" >  
<property name="attributeRepository" ref="attributeRepository" /> // 
增長此屬性,爲認證過的用戶的 Principal 添加屬性 
</bean> 
<bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" /> 
</list> 
</property> 

3.2 
修改該文件中默認的 attributeRepositorybean 配置 
<!-- 
使用 SingleRowJdbcPersonAttributeDao 獲取更多用戶的信息 --> 
<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"> 
<constructor-arg index="0" ref="dataSource"/> 
<constructor-arg index="1" value="select role_name,group_name from role where login_name = ?"/>  
<!-- 
這裏的 key 需寫 username,value 對應數據庫用戶名字段 --> 
<property name="queryAttributeMapping"> 
<map> 
<entry key="username" value="login_name"/> 
</map> 
</property> 
<!--key 
對應數據庫字段, value 對應客戶端獲取參數 --> 
<property name="resultAttributeMapping"> 
<map> 
<entry key="role_name" value="authorities"/> // 
這個從數據庫中獲取的角色,用於在應用中 security 的權限驗證 
</map> 
</property> 
</bean>
tomcat

3.3 修改該文件中最默認的 serviceRegistryDao 中的屬性所有註釋掉 
這個 bean 中的 RegisteredServiceImpl  ignoreAttributes 屬性將決定是否添加 attributes 屬性內容,默認爲 false: 不添加,只有去掉這個配置, cas server 纔會將獲取的用戶的附加屬性添加到認證用的 Principal  attributes 中去。 
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"></bean>
安全

3.4 若採用 CAS  Cas20ServiceTicketValidator 認證,則須要修改 WEB-INFviewjspprotocol2.0casServiceValidationSuccess.jsp 文件,才能把獲取的屬性傳遞至客戶端 
<%@ page session="false" %> 
<%@ taglib prefix="c" uri=" 
http://java.sun.com/jsp/jstl/core " %> 
<%@ taglib uri=" 
http://java.sun.com/jsp/jstl/functions " prefix="fn" %> 
<cas:serviceResponse xmlns:cas=\'http://www.yale.edu/tp/cas\'> 
<cas:authenticationSuccess> 
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user> 

<c:if test="${not empty pgtIou}"> 
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket> 
</c:if> 
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}"> 
<cas:proxies> 
<c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1"> 
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy> 
</c:forEach> 
</cas:proxies> 
</c:if> 
<!-- 
增長以下內容 --> 
<c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)> 0}"> 
<cas:attributes> 
<c:forEach  
var="attr" 
items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}" 
varStatus="loopStatus"  
begin="0" 
end="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)-1}" 
step="1"> 
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}> 
</c:forEach> 
</cas:attributes> 
</c:if> 
</cas:authenticationSuccess> 
</cas:serviceResponse>
session

至此, CAS Server 搭建完畢。app

3、搭建 CAS Client (即 Spring Security )應用

1. CAS Client 下須要把 spring-security-cas-3.1.0.M2.jar  Spring Security 相關的jar 引入,把 cas-client-core-3.2.0.jar 引入,用於從 cas server 上獲取相關認證與受權信息。

2. CAS Client 應用的 web.xml  增長以下 
<!-- spring 
配置文件 - -> 
<context-param> 
<param-name>contextConfigLocation</param-name> 
<param-value>classpath:applicationContext-security-ns.xml</param-value> 
</context-param>

<!-- spring security filter --> 
<filter> 
<filter-name>springSecurityFilterChain</filter-name> 
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter>

<filter-mapping> 
<filter-name>springSecurityFilterChain</filter-name> 
<url-pattern>/*</url-pattern> 
</filter-mapping>

<!-- spring 默認偵聽器 --> 
<listener> 
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener>

3. spring security 文件的配置 applicationContext-security-ns.xml

<?xml version="1.0"?> 
<beans xmlns=" 
http://www.springframework.org/schema/beans  
xmlns:security=" 
http://www.springframework.org/schema/security  
xmlns:xsi=" 
http://www.w3.org/2001/XMLSchema-instance  
xsi:schemaLocation=" 
http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
http://www.springframework.org/schema/security   http://www.springframework.org/schema/security/spring-security-3.1.xsd ">

<!-- 
Enable security, let the casAuthenticationEntryPoint handle all intercepted urls. 
The CAS_FILTER needs to be in the right position within the filter chain. 
-->  
<security:http entry-point-ref="casAuthenticationEntryPoint" auto-config="true"> 
<security:intercept-url pattern="/**" access="ROLE_USER"></security:intercept-url> 
<security:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter"></security:custom-filter> 
</security:http>

<!-- 
Required for the casProcessingFilter, so define it explicitly set and 
specify an Id Even though the authenticationManager is created by 
default when namespace based config is used. 
--> 
<security:authentication-manager alias="authenticationManager"> 
<security:authentication-provider ref="casAuthenticationProvider"></security:authentication-provider> 
</security:authentication-manager>

<!-- 
This section is used to configure CAS. The service is the 
actual redirect that will be triggered after the CAS login sequence. 
--> 
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"> 
//http://localhost:8088/SpringSecurity 
具體應用 
// j_spring_cas_security_check spring 
的虛擬 URL ,此標誌標識使用 CAS authentication upon return from CAS SSO login. 
<property name="service" value=" 
http://localhost:8088/SpringSecurity/j_spring_cas_security_check"></property > 
<property name="sendRenew" value="false"></property> 
</bean>

<!-- 
The CAS filter handles the redirect from the CAS server and starts the ticket validation. 
--> 
<bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> 
<property name="authenticationManager" ref="authenticationManager"></property> 
</bean>

<!-- 
The entryPoint intercepts all the CAS authentication requests. 
It redirects to the CAS loginUrl for the CAS login page. 
--> 
<bean id="casAuthenticationEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"> 
<property name="loginUrl" value=" 
http://localhost:8080/cas/login"></property> //SSO 登陸地址 
<property name="serviceProperties" ref="serviceProperties"></property> 
</bean>

<!-- 
Handles the CAS ticket processing. 
--> 
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> 
<property name="authenticationUserDetailsService" ref="authenticationUserDetailsService"/> 
<property name="serviceProperties" ref="serviceProperties"></property> 
<property name="ticketValidator"> 
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> 
<constructor-arg index="0" value=" 
http://localhost:8080/cas " /> //SSO 驗證地址 
</bean> 
</property> 
<property name="key" value="cas"></property> 

</bean> 
<!-- authorities 
對應 CAS server  登陸屬性, 在此設置到 spirng security 中,用於spring security 的驗證 --> 
<bean id="authenticationUserDetailsService" class="org.springframework.security.cas.userdetails.GrantedAuthorityFromAssertionAttributesUserDetailsService"> 
<constructor-arg> 
<array> 
<value>authorities</value> 
</array> 
</constructor-arg> 
</bean> 
</beans>

至此, CAS 客戶端搭建完畢。

4、總結

經過上述的配置,則具體應用在使用的時候,用戶認證和受權則無需過問,只需在應用中配置相關的角色訪問權限便可。即,只需對下面的紅色部分進行修改,便可以完成應用的認證和受權工做。大大簡化了應用和認證與受權的剝離工做

<security:http entry-point-ref="casAuthenticationEntryPoint" auto-config="true"> 
<security:intercept-url pattern="/**" access="ROLE_USER"></security:intercept-url>  
<security:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter"></security:custom-filter> 
</security:http>

5、擴展

若在同一 SSO 下有多個應用, 同一戶在不一樣應用下有不一樣的角色,則考慮擴展獲取用戶權限的環節;資源和角色在數據庫中進行配置等等。

相關文章
相關標籤/搜索