一、單點登錄CAS介紹
1.1 什麼是單點登錄CAS
單點登錄(Single Sign On),簡稱爲 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。
1.2 單點登錄的應用場景
在系統的開發過程中,如果個系統包含多個子系統,而這些子系統又共用一個認證數據庫(可以理解爲多個子系統登錄的用戶信息都保存在一個數據庫)。這樣就會涉及到一個場景:用戶登錄過任何一個子系統後,再訪問其他的子系統時,不再需要重複登錄。這就涉及到單點登錄的問題。
例如:有三個子系統A、B、C。登錄時用的是同一套數據庫,三個系統間可以互相跳轉。目標是:三個系統中其中一個登錄了,其他兩個就無需登錄驗證。
二、單點登錄服務器的完整配置
2.1原生的CAS服務器登錄界面效果
原生的CAS服務器,其實就是一個war包。要運行CAS服務器,直接將war包部署到tomcat服務器中即可運行查看效果。原生的cas.war部署後,訪問的界面效果如下圖:
登錄默認的CAS服務器的用戶名和密碼是: casuser/Mellon
2.2 修改CAS在開發中常用配置(修改商品和https校驗忽略)
2.2.1 修改訪問端口
- 修改tomcat的端口號
打開tomcat主目錄中,conf/server.xml文件
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- 修改CAS配置文件端口號
修改cas.war主目錄中 WEB-INF/cas.properties
下面的端口號設置爲與 tomcat修改的端口一致。
server.name=http://localhost:9100
2.2.2 去除https的認證
CAS 默認使用的是 HTTPS 協議,如果使用 HTTPS 協議需要 SSL 安全證書(需向特定的機構申請和購買) 。如果對安全要求不高或是在開發測試階段,可使用 HTTP 協議。我們這裏講解通過修改配置,讓 CAS 使用 HTTP 協議。
- 修改cas的WEB-INF/deployerConfigContext.xml
這裏需要增加參數 p:requireSecure=“false”,requireSecure 屬性意思爲是否需要安全驗證,即HTTPS,false 爲不採用<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient"/>
- 修改cas的WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml
參數 p:cookieSecure=“true”,同理爲 HTTPS 驗證相關,TRUE 爲採用 HTTPS 驗證,FALSE 爲不採用 https 驗證。<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="true" p:cookieMaxAge="-1" p:cookieName="CASTGC" p:cookiePath="/cas" />
參數 p:cookieMaxAge="-1",是 COOKIE 的最大生命週期,-1 爲無生命週期,即只在當前打開的窗口有效,關閉或重新打開其它窗口,仍會要求驗證。可以根據需要修改爲大於 0 的數字,比如 3600 等,意思是在 3600 秒內,打開任意窗口,都不需要驗證。
這裏將 cookieSecure 改爲 false , cookieMaxAge 改爲 3600 - 修改cas的WEB-INF/spring-configuration/warnCookieGenerator.xml
這裏將 cookieSecure 改爲 false , cookieMaxAge 改爲 3600<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="true" p:cookieMaxAge="-1" p:cookieName="CASPRIVACY" p:cookiePath="/cas" />
2.2.3 設置“退出登錄”時自動跳轉的界面
- 修改 cas 系統的配置文件 cas-servlet.xml
<bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction"
p:servicesManager-ref="servicesManager"
p:followServiceRedirects="${cas.logout.followServiceRedirects:false}"/>
將cas.logout.followServiceRedirects的值修改爲“true"
2. 在系統中,退出系統的按鈕中,發起請求時,超鏈接進行如下修改
<a href="http://localhost:9100/cas/logout?service=希望跳轉的界面或是URL請求">退出登錄</a>
2.2.4 修改CAS連接系統數據庫動態校驗密碼
-
修改 cas 服務端中 web-inf 下 deployerConfigContext.xml中最後添加下面3項配置
<!--p:jdbcUrl:設置連接數據庫的URL地址;p:user:登錄數據庫的用戶名;p:password:登錄數據庫的密碼 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" p:driverClass="com.mysql.jdbc.Driver" p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/pinyougoudb?characterEncoding=utf8" p:user="root" p:password="123456" />
<!-- 注意c:encodingAlgorithm:參數指定當前驗證密碼時的加密方式 --> <bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" c:encodingAlgorithm="MD5" p:characterEncoding="UTF-8" />
<!--p:sql:指定連接數據庫後,根據用戶名查詢密碼的 sql語句 --> <bean id="dbAuthHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler" p:dataSource-ref="dataSource" p:sql="select password from tb_user where username = ?" p:passwordEncoder-ref="passwordEncoder"/>
-
將配置的dbAuthHandler注入到認證管理器authenticationManager中
在當前配置文件中,查找如下配置信息的位置
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
將這個bean下的 property屬性修改爲第1步中配置的dbAuthHandler,具體操作如下
將
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
修改爲<entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver"/>
-
將下面cas所依賴的3個jar包放置到cas.war目錄中的lib文件夾中
c3p0-0.9.1.2.jar cas-server-support-jdbc-4.0.0.jar mysql-connector-java-5.1.32.jar
3.4 修改CAS默認的登錄界面爲與集成的工程配套的
- cas.war默認的登錄界面在目錄 WEB-INF\view\jsp\default\ui\casLoginView.jsp。實現對CAS登錄界面的更換,只需將集成工程中的login界面替換casLoginView.jsp界面即可。具體操作步驟如下
-
將集成工程中的登錄界面整體複製到casLoginView.jsp中
-
把下面的指令添加到更換後的casLoginView.jsp界面
<%@ page pageEncoding="UTF-8" %> <%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
修改form表單的標籤
<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true" class="sui-form">
-
修改登錄用戶名和登錄密碼的input框
<form:input id="username" tabindex="1" accesskey="${userNameAccessKey}" path="username" autocomplete="off" htmlEscape="true" placeholder="郵箱/用戶名/手機號" class="span2 input-xfat" />
<form:password id="password" tabindex="2" path="password" accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" placeholder="請輸入密碼" class="span2 input-xfat" />
-
修改登錄按鈕
<input type="hidden" name="lt" value="${loginTicket}" /> <input type="hidden" name="execution" value="${flowExecutionKey}" /> <input type="hidden" name="_eventId" value="submit" /> <input class="sui-btn btn-block btn-xlarge btn-danger" accesskey="l" value="登陸" type="submit" />
二、單點登錄案例中web.xml配置介紹
2.1配置單點登出的信息
<!-- 配置 單點登出 -->
<!-- 用於單點退出,該過濾器用於實現單點登出功能,可選配置 -->
<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>
- 訪問“登出“的URL,固定是 /logout。
- 我們這裏訪問登出的URL:http://localhst:9100/cas/logout
2.2 配置單點登錄的信息
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<!-- 配置如果當前工程未登錄,則會跳轉到 CAS的登錄界面 -->
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:9100/cas/login</param-value>
<!--這裏的server是服務端的IP -->
</init-param>
<init-param>
<!-- 統一配置,訪問CAS服務器根路徑 -->
<param-name>serverName</param-name>
<param-value>http://localhost:9001</param-value>
</init-param>
</filter>
<filter-mapping>
<!-- 配置 過濾器CASFilter 將會攔截哪些 URL請求-->
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.3 配置票據管理的信息
<!-- 該過濾器負責對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>http://localhost:9100/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9001</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、springsecurity與CAS整合案例
重點要將Spring-security.xml配置文件理解
3.1 配置總的配置信息
<http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
<intercept-url pattern="/**" access="ROLE_USER"/>
<csrf disabled="true"/>
<!-- filter 都是 spring-security框架內置的 -->
<!-- custom-filter爲過濾器, position 表示將過濾器放在指定的位置上,before表示放在指定位置之前 ,after表示放在指定的位置之後 -->
<!-- 登錄的配置-->
<custom-filter ref="casAuthenticationFilter" position="CAS_FILTER" />
<!--登出的配置-->
<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</http>
3.2 認證過濾器的開始部分
<beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<!-- 認證管理器 -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<!-- 認證提供者 -->
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService">
<beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<!-- 配置加載Spring-security框架的自定義認證類-->
<beans:constructor-arg ref="userDetailsService" />
</beans:bean>
</beans:property>
<beans:property name="serviceProperties" ref="serviceProperties"/>
<!-- ticketValidator 爲票據驗證器。指定了獲取票據信息的CAS的訪問根URL -->
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0" value="http://localhost:9100/cas"/>
</beans:bean>
</beans:property>
<beans:property name="key" value="an_id_for_this_auth_provider_only"/>
</beans:bean>
<!-- 認證類:配置spring-security中認證操作的自定義實現類。作用:加載當前登錄用戶的角色列表 -->
<beans:bean id="userDetailsService" class="cn.itcast.demo.service.UserDetailServiceImpl"/>
<!-- 配置整合spring-security和cas工程後的 本地登錄訪問的URL-->
<beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<!--service 配置自身工程的根地址+/login/cas 如果登出,則會跳轉到當前所配置的URL路徑中 -->
<beans:property name="service" value="http://localhost:9003/login/cas"/>
</beans:bean>
3.3 配置登出的信息
- requestSingleLogoutFilter
<!-- 經過此配置,當用戶在地址欄輸入本地工程 /logout/cas -->
<beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<!--配置cas退出成功,將會跳轉的界面-->
<beans:constructor-arg value="http://localhost:9100/cas/logout?service=http://localhost:9003/login.html"/>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout/cas"/>
</beans:bean>
- 配置singleLogoutFilter登出過濾器的配置
<beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>