這篇文章對CAS單點登錄具體實現的一些步驟就行講述,至於CAS單點登錄的實現原理分析,請參看下面這篇文章:
CAS單點登錄原理分析(一) https://blog.csdn.net/qq_41258204/article/details/84036875
CAS 包含兩個部分: CAS Server 和 CAS Client 。
CAS Server :其實就是一個war包,CAS框架已經提供。只需要把部署到web服務器上即可,主要負責對用戶的認證工作。 在文章末尾的示例項目中提供。
CAS Client:就是開發過程中的web層, 負責處理對客戶端受保護資源的訪問請求,需要登錄時,重定向到 CAS Server。不需要對這個部分進行過多編碼,進行簡單配置即可。
一,CAS 服務端部署
本次使用的CAS服務端版本是cas-server-4.0.0-release
,
1.將cas-server-4.0.0-release\cas-server-4.0.0\modules
文件夾下cas-server-webapp-4.0.0.war
文件放入 tomcat 目錄下的 webapps 下,文件改名爲cas.war,爲了訪問時方便。
2.啓動tomcat ,tomcat將自動解壓 war 包。訪問tomcat下這個項目,就能看到它的登錄頁面。
其實訪問的是服務端的首頁index.jsp,觀察上面的地址欄,發現是對請求地址進行了重寫,跳轉到了登錄頁面。有些小夥伴奇怪這個是怎麼做到的,通過查看服務端的index.jsp會發現,這個一點也不神奇。
注意:CAS Server服務端的登錄界面是可以進行改動的,不然項目上線後,用戶的登錄體驗忒差了點。這個不用擔心!
3.用戶名和密碼配置
在\apache-tomcat-cas\webapps\cas\WEB-INF目錄下的deployerConfigContext.xml配置
也可以連接數據庫查詢用戶名和密碼,這裏先寫死。
修改配置,重啓tomcat服務器,輸入用戶名,密碼,看到success頁面
4.服務端訪問端口修改
不想使用8080 端口訪問 CAS Server服務端, 可以修改訪問端口
4.1首先修改tomcat的訪問端口
修改\apache-tomcat-cas\conf目錄的server.xml文件
80爲http協議默認端口,下次再訪問tomcat就不用加端口號,修改其它端口也可以。
4.2修改 CAS 配置文件
修改 cas 的 WEB-INF/cas.properties
server.name=http://localhost:80
- 修改cas項目的訪問路徑(可選)
修改apache-tomcat-cas\conf目錄下的server.xml文件, 添加如下配置
<Context path="" docBase="cas" reloadable="true"/>
完成上述修改,重啓tomcat服務,輸入localhost就可以訪問到登錄頁面
6.本地域名解析(可選)
如果覺得輸入localhost覺得彆扭,還可以進行域名解析配置,不過這個域名只能在自己電腦上使用。
6.1修改C:\Windows\System32\drivers\etc目錄下的hosts文件
快設置一個自己喜歡的域名吧,記得用管理員身份編輯哦!
6.2不過我更習慣用下面這種方式配置本地域名解析
注意:這款軟件要以管理員身份運行!
這款軟件,在文章末的實例項目中提供。再次訪問CAS Server服務端,一切正常。
7.去除CAS的 https 認證
使用了https協議的網站
網站的地址欄前面會有一個小鎖,使用https也是爲了網站更加安全。
CAS 默認使用的是 HTTPS 協議,如果使用 HTTPS 協議需要 SSL 安全證書(需向特定的機構申請和購買) ,在開發測試階段可以先使用http協議。
7.1修改 cas 的 WEB-INF/deployerConfigContext.xml
找到如下配置
添加一個屬性設置p:requireSecure="false"
。默認爲true,需要安全驗證,使用的是https協議。
bean id="proxyAuthenticationHandler"
class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false"/>
7.2修改 cas 的/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml
p:cookieSecure="false"
p:cookieMaxAge="3600"
p:cookieName="CASTGC"
p:cookiePath="/cas"
7.3修改 cas 的 WEB-INF/spring-configuration/warnCookieGenerator.xml
找到上述配置,修改如下
p:cookieSecure="false"
p:cookieMaxAge="3600"
p:cookieName="CASPRIVACY"
p:cookiePath="/cas"
修改完配置,重啓tomcat,訪問CAS Server服務,一切正常。關閉瀏覽器後,再次打開瀏覽器訪問,直接顯示已經登錄。說明cookie有效時間設置成功,會話cookie設置成了持久性cookie。
8.CAS 修改服務端登錄頁面
8.1將準備的登陸頁面login.html 拷貝到 cas 的 WEB-INF\view\jsp\default\ui 目錄下
8.2將原來的 casLoginView.jsp 改名,將 login.html 改名爲 casLoginView.jsp
8.3將準備的login.html需要的 css js img 文件夾拷貝到 cas 目錄下
8.4修改準備的登錄頁面casLoginView.jsp
對照原來的登錄頁面進行修改
打開原來的登錄頁面,裏面引入了top.jsp頁面
在cas的WEB-INF\view\jsp\default\ui\includes目錄下找到top.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" %>
修改完成後,重新訪問CAS Server服務端,看到頁面修改成功
到這表面看起來都已經修改完成,其實真正的內容還沒有修改。form表單,輸入框和登錄按鈕,還需要進一步修改。
8.5修改form表單
打開原來的登錄頁面,找到如下部分
<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true">
<form:errors path="*" id="msg" cssClass="errors" element="div" htmlEscape="false" />
</form:form>
將上面的form標籤複製到準備的登錄頁面上,將準備的登錄頁面的form標籤刪除
8.6修改用戶名輸入框
打開原來的登錄頁面,找到如下部分
<form:input cssClass="required" cssErrorClass="error" id="username" size="25" tabindex="1" accesskey="${userNameAccessKey}" path="username" autocomplete="off" htmlEscape="true" />
將上面的input標籤複製到準備的登錄頁面上,刪除上面標籤中的cssClass,cssErrorClass樣式,換成準備的登錄頁面上用戶名輸入框的樣式
<form:input class="text" style="color: #FFFFFF !important" placeholder="請輸入賬戶" id="username" size="25" tabindex="1" accesskey="${userNameAccessKey}" path="username" autocomplete="off" htmlEscape="true" />
8.7修改密碼輸入框
打開原來的登錄頁面,找到如下部分
<form:password cssClass="required" cssErrorClass="error" id="password" size="25" tabindex="2" path="password" accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" />
將上面的password標籤複製到準備的登錄頁面上,刪除上面標籤中的cssClass,cssErrorClass樣式,換成準備的登錄頁面上密碼輸入框的樣式
<form:password class="text" style="color: #FFFFFF !important; position:absolute; z-index:100;" placeholder="請輸入密碼" id="password" size="25" tabindex="2" path="password" accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" />
8.8 修改登錄按鈕
打開原來的登錄頁面,找到如下部分
<input type="hidden" name="lt" value="${loginTicket}" />
<input type="hidden" name="execution" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
<input class="btn-submit" name="submit" accesskey="l" value="<spring:message code="screen.welcome.button.login" />" tabindex="4" type="submit" />
將上面的內容複製到準備的登錄頁面上,刪除上面標籤中的 class=“btn-submit”,<spring:message code=“screen.welcome.button.login” />,換成準備的登錄頁面上按鈕的樣式
<a class="act-but submit" href="javascript:document.getElementById('fm1').submit()" style="color: #FFFFFF" name="submit" accesskey="l" value="登錄" tabindex="4" />登錄</a>
訪問修改好的登錄頁面,當輸入用戶名或密碼錯誤,給出的提示信息不是很友好
8.9 修改錯誤提示
上面的英文錯誤提示信息是在cas的 WEB-INF\classes 目錄下的 messages.properties 文件中
authenticationFailure.AccountNotFoundException=Invalid credentials.
authenticationFailure.FailedLoginException=Invalid credentials.
第一個是用戶名不存在時的錯誤提示
第二個是密碼錯誤的提示
將上面的兩行內容複製到 messages_zh_CN.properties 文件中,這個文件主要是配置一些中文信息的,這個裏面裏面的內容是進行轉碼提示的
這個跟properties屬性文件很類似,所以可以藉助properties文件來完成中文提示內容的寫入
將上述內容替換掉Invalid credentials英文提示
authenticationFailure.AccountNotFoundException=\u7528\u6237\u540D\u6216\u5BC6\u7801\u9519\u8BEF.
authenticationFailure.FailedLoginException=\u7528\u6237\u540D\u6216\u5BC6\u7801\u9519\u8BEF.
設置國際化爲 zn_CN ,修改cas的WEB-INF目錄下 cas-servlet.xml,優先使用配置中文提示信息的messages_zh_CN.properties 文件
搜索en關鍵字,快速找到這行信息,默認使用的是英文國際化
修改爲:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"
p:defaultLocale="zh_CN" />
修改完配置後,重啓tomcat,再次訪問CAS Server服務端
建議每修改一步就刷新頁面進行查看,防止出錯!
9.CAS server 自定義認證方式
9.1打開cas服務端WEB-INF目錄下的deployerConfigContext.xml文件 ,找到如下配置
以上就是cas默認的認證方式,把用戶名和密碼寫死在配置文件中。下面自定義認證方式,通過數據庫中的用戶信息,來認證登錄的用戶。
9.2自定義認證
主要配置:
數據源dataSource,從數據庫中查詢用戶信息
密碼加密方式passwordEncoder,可選配置,可以自定義加密方式
認證方式 dbAuthHandler,主要引用數據源,查詢sql和密碼加密方式都可以自定義
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/cas?characterEncoding=utf8"
p:user="root"
p:password="root" />
<bean id="passwordEncoder"
class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
c:encodingAlgorithm="MD5"
p:characterEncoding="UTF-8" />
<bean id="dbAuthHandler"
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"
p:dataSource-ref="dataSource"
p:sql="select password from t_user where username = ?"
p:passwordEncoder-ref="passwordEncoder"/>
把以上三個配置複製到deployerConfigContext.xml
文件中最後,修改認證方式爲自定義認證方式
<entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver" />
9.3導入相關jar包
由於自定義認證方式使用數據庫作爲數據源,需要在cas\WEB-INF\lib 目錄下導入以下jar包
修改完成後,重啓tomcat,使用數據庫中的數據進行測試
二, CAS 客戶端配置
1.創建Maven工程(war) cas_shoppingclient,引入CAS客戶端相關依賴,設置tomcat的訪問端口8081
<dependencies>
<!-- CAS客戶端 -->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.3.3</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>8081</port>
</configuration>
</plugin>
<!-- 設置jdk版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
- 在webapp目錄下創建WEB-INF文件夾,添加web.xml文件
web.xml文件主要配置:
單點登出過濾器SingleSignOutFilter:執行用戶退出時的操作(可選)
認證過濾器AuthenticationFilter:負責用戶認證(必須)
ticket驗證過濾器Cas20ProxyReceivingTicketValidationFilter:負責檢驗ticket(必須)
獲取用戶登錄名過濾器
HttpServletRequestWrapperFilter(可選)和AssertionThreadLocalFilter
(可選)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<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>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<!-- CAS服務端如果訪問端口配置爲80,訪問路徑配置path="" 下面地址可以改成http://cas.xiaogui.com -->
<param-value>http://cas.xiaogui.com:80/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<!-- 客戶端地址,用於認證成功後,跳轉回客戶端 -->
<param-value>http://shopping.xiaogui.com:8081</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</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>
<!-- CAS服務端如果訪問端口配置爲80,訪問路徑配置path="" 下面地址可以改成http://cas.xiaogui.com -->
<param-value>http://cas.xiaogui.com:80/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<!-- 客戶端地址,用於認證成功後,跳轉回客戶端 -->
<param-value>http://shopping.xiaogui.com:8081</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>
</web-app>
注意:配置CAS Server服務端地址和CAS Client客戶端地址一定要對應
3.編寫index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>購物車</title>
</head>
<body>
<h1>歡迎訪問購物車系統,當前的用戶名:<%=request.getRemoteUser() %></h1>
</body>
</html>
request.getRemoteUser()爲獲取遠程登錄名
4.創建Maven工程(war) cas_payclient客戶端,參照cas_shoppingclient客戶端進行配置
5.創建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品結算</title>
</head>
<body>
<h1>歡迎訪問商品結算系統,當前的用戶名:<%=request.getRemoteUser() %></h1>
</body>
</html>
6.單點登錄測試
啓動cas服務端
啓動客戶端cas_shoppingclient和客戶端cas_payclient
訪問cas_shoppingclient客戶端
輸入帳號,密碼登錄
訪問cas_payclient客戶端
直接登錄成功!
7.cas單點退出登錄到指定頁面
地址欄輸入 http://cas.xiaogui.com/cas/logout
即可看到退出後的提示頁面
自定義退出登錄跳轉地址
找到如cas服務端 WEB-INF目錄的配置文件 cas-servlet.xml如下配置
p:followServiceRedirects="${cas.logout.followServiceRedirects:true}
在cas_shoppingclient客戶端index.jsp頁面上添加一個退出鏈接
<a href="http://cas.xiaogui.com/cas/logout?service=https://blog.csdn.net/qq_41258204">退出登錄</a>
分享示例項目在碼雲上的地址:https://gitee.com/xiaoguixiaogege/SSO_CAS
未完,待續!