<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    J2EE社區

    茍有恒,何必三更起五更眠;
    最無益,只怕一日曝十日寒.
    posts - 241, comments - 318, trackbacks - 0, articles - 16

    使用 CAS 在 Tomcat 中實現單點登錄

    Posted on 2010-04-13 10:21 xcp 閱讀(2563) 評論(0)  編輯  收藏 所屬分類: JAVA

    CAS 介紹

    CAS 是 Yale 大學發起的一個開源項目,旨在為 Web 應用系統提供一種可靠的單點登錄方法,CAS 在 2004 年 12 月正式成為 JA-SIG 的一個項目。CAS 具有以下特點:

    • 開源的企業級單點登錄解決方案。
    • CAS Server 為需要獨立部署的 Web 應用。
    • CAS Client 支持非常多的客戶端(這里指單點登錄系統中的各個 Web 應用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

    CAS 原理和協議

    從結構上看,CAS 包含兩個部分: CAS Server 和 CAS Client。CAS Server 需要獨立部署,主要負責對用戶的認證工作;CAS Client 負責處理對客戶端受保護資源的訪問請求,需要登錄時,重定向到 CAS Server。圖1 是 CAS 最基本的協議過程:


    圖 1. CAS 基礎協議
    CAS 基礎協議

    CAS Client 與受保護的客戶端應用部署在一起,以 Filter 方式保護受保護的資源。對于訪問受保護資源的每個 Web 請求,CAS Client 會分析該請求的 Http 請求中是否包含 Service Ticket,如果沒有,則說明當前用戶尚未登錄,于是將請求重定向到指定好的 CAS Server 登錄地址,并傳遞 Service (也就是要訪問的目的資源地址),以便登錄成功過后轉回該地址。用戶在第 3 步中輸入認證信息,如果登錄成功,CAS Server 隨機產生一個相當長度、唯一、不可偽造的 Service Ticket,并緩存以待將來驗證,之后系統自動重定向到 Service 所在地址,并為客戶端瀏覽器設置一個 Ticket Granted Cookie(TGC),CAS Client 在拿到 Service 和新產生的 Ticket 過后,在第 5,6 步中與 CAS Server 進行身份合適,以確保 Service Ticket 的合法性。

    在該協議中,所有與 CAS 的交互均采用 SSL 協議,確保,ST 和 TGC 的安全性。協議工作過程中會有 2 次重定向的過程,但是 CAS Client 與 CAS Server 之間進行 Ticket 驗證的過程對于用戶是透明的。

    另外,CAS 協議中還提供了 Proxy (代理)模式,以適應更加高級、復雜的應用場景,具體介紹可以參考 CAS 官方網站上的相關文檔。

    準備工作

    本文中的例子以 tomcat5.5 為例進行講解,下載地址:

    http://tomcat.apache.org/download-55.cgi

    到 CAS 官方網站下載 CAS Server 和 Client,地址分別為:

    http://www.ja-sig.org/downloads/cas/cas-server-3.1.1-release.zip

    http://www.ja-sig.org/downloads/cas-clients/cas-client-java-2.1.1.zip





    回頁首


    部署 CAS Server

    CAS Server 是一套基于 Java 實現的服務,該服務以一個 Java Web Application 單獨部署在與 servlet2.3 兼容的 Web 服務器上,另外,由于 Client 與 CAS Server 之間的交互采用 Https 協議,因此部署 CAS Server 的服務器還需要支持 SSL 協議。當 SSL 配置成功過后,像普通 Web 應用一樣將 CAS Server 部署在服務器上就能正常運行了,不過,在真正使用之前,還需要擴展驗證用戶的接口。

    在 Tomcat 上部署一個完整的 CAS Server 主要按照以下幾個步驟:

    配置 Tomcat 使用 Https 協議

    如果希望 Tomcat 支持 Https,主要的工作是配置 SSL 協議,其配置過程和配置方法可以參考 Tomcat 的相關文檔。不過在生成證書的過程中,會有需要用到主機名的地方,CAS 建議不要使用 IP 地址,而要使用機器名或域名。

    部署 CAS Server

    CAS Server 是一個 Web 應用包,將前面下載的 cas-server-3.1.1-release.zip 解開,把其中的 cas-server-webapp-3.1.1.war 拷貝到 tomcat的 webapps 目錄,并更名為 cas.war。由于前面已配置好 tomcat 的 https 協議,可以重新啟動 tomcat,然后訪問:https://localhost:8443/cas ,如果能出現正常的 CAS 登錄頁面,則說明 CAS Server 已經部署成功。

    雖然 CAS Server 已經部署成功,但這只是一個缺省的實現,在實際使用的時候,還需要根據實際概況做擴展和定制,最主要的是擴展認證 (Authentication) 接口和 CAS Server 的界面。

    擴展認證接口

    CAS Server 負責完成對用戶的認證工作,它會處理登錄時的用戶憑證 (Credentials) 信息,用戶名/密碼對是最常見的憑證信息。CAS Server 可能需要到數據庫檢索一條用戶帳號信息,也可能在 XML 文件中檢索用戶名/密碼,還可能通過 LDAP Server 獲取等,在這種情況下,CAS 提供了一種靈活但統一的接口和實現分離的方式,實際使用中 CAS 采用哪種方式認證是與 CAS 的基本協議分離開的,用戶可以根據認證的接口去定制和擴展。

    擴展 AuthenticationHandler

    CAS 提供擴展認證的核心是 AuthenticationHandler 接口,該接口定義如清單 1 下:


    清單 1. AuthenticationHandler定義
                    
    public interface AuthenticationHandler {
    /**
    * Method to determine if the credentials supplied are valid.
    * @param credentials The credentials to validate.
    * @return true if valid, return false otherwise.
    * @throws AuthenticationException An AuthenticationException can contain
    * details about why a particular authentication request failed.
    */
    boolean authenticate(Credentials credentials) throws AuthenticationException;
    /**
    * Method to check if the handler knows how to handle the credentials
    * provided. It may be a simple check of the Credentials class or something
    * more complicated such as scanning the information contained in the
    * Credentials object.
    * @param credentials The credentials to check.
    * @return true if the handler supports the Credentials, false othewrise.
    */
    boolean supports(Credentials credentials);
    }

    該接口定義了 2 個需要實現的方法,supports ()方法用于檢查所給的包含認證信息的Credentials 是否受當前 AuthenticationHandler 支持;而 authenticate() 方法則擔當驗證認證信息的任務,這也是需要擴展的主要方法,根據情況與存儲合法認證信息的介質進行交互,返回 boolean 類型的值,true 表示驗證通過,false 表示驗證失敗。

    CAS3中還提供了對AuthenticationHandler 接口的一些抽象實現,比如,可能需要在執行authenticate() 方法前后執行某些其他操作,那么可以讓自己的認證類擴展自清單 2 中的抽象類:


    清單 2. AbstractPreAndPostProcessingAuthenticationHandler定義
                    
    public abstract class AbstractPreAndPostProcessingAuthenticationHandler
    implements AuthenticateHandler{
    protected Log log = LogFactory.getLog(this.getClass());
    protected boolean preAuthenticate(final Credentials credentials) {
    return true;
    }
    protected boolean postAuthenticate(final Credentials credentials,
    final boolean authenticated) {
    return authenticated;
    }
    public final boolean authenticate(final Credentials credentials)
    throws AuthenticationException {
    if (!preAuthenticate(credentials)) {
    return false;
    }
    final boolean authenticated = doAuthentication(credentials);
    return postAuthenticate(credentials, authenticated);
    }
    protected abstract boolean doAuthentication(final Credentials credentials)
    throws AuthenticationException;
    }


    AbstractPreAndPostProcessingAuthenticationHandler 類新定義了 preAuthenticate() 方法和 postAuthenticate() 方法,而實際的認證工作交由 doAuthentication() 方法來執行。因此,如果需要在認證前后執行一些額外的操作,可以分別擴展 preAuthenticate()和 ppstAuthenticate() 方法,而 doAuthentication() 取代 authenticate() 成為了子類必須要實現的方法。

    由于實際運用中,最常用的是用戶名和密碼方式的認證,CAS3 提供了針對該方式的實現,如清單 3 所示:


    清單 3. AbstractUsernamePasswordAuthenticationHandler 定義
                    
    public abstract class AbstractUsernamePasswordAuthenticationHandler extends
    AbstractPreAndPostProcessingAuthenticationHandler{
    ...
    protected final boolean doAuthentication(final Credentials credentials)
    throws AuthenticationException {
    return authenticateUsernamePasswordInternal((UsernamePasswordCredentials) credentials);
    }
    protected abstract boolean authenticateUsernamePasswordInternal(
    final UsernamePasswordCredentials credentials) throws AuthenticationException;
    protected final PasswordEncoder getPasswordEncoder() {
    return this.passwordEncoder;
    }
    public final void setPasswordEncoder(final PasswordEncoder passwordEncoder) {
    this.passwordEncoder = passwordEncoder;
    }
    ...
    }

    基于用戶名密碼的認證方式可直接擴展自 AbstractUsernamePasswordAuthenticationHandler,驗證用戶名密碼的具體操作通過實現 authenticateUsernamePasswordInternal() 方法達到,另外,通常情況下密碼會是加密過的,setPasswordEncoder() 方法就是用于指定適當的加密器。

    從以上清單中可以看到,doAuthentication() 方法的參數是 Credentials 類型,這是包含用戶認證信息的一個接口,對于用戶名密碼類型的認證信息,可以直接使用 UsernamePasswordCredentials,如果需要擴展其他類型的認證信息,需要實現Credentials接口,并且實現相應的 CredentialsToPrincipalResolver 接口,其具體方法可以借鑒 UsernamePasswordCredentials 和 UsernamePasswordCredentialsToPrincipalResolver。

    JDBC 認證方法

    用戶的認證信息通常保存在數據庫中,因此本文就選用這種情況來介紹。將前面下載的 cas-server-3.1.1-release.zip 包解開后,在 modules 目錄下可以找到包 cas-server-support-jdbc-3.1.1.jar,其提供了通過 JDBC 連接數據庫進行驗證的缺省實現,基于該包的支持,我們只需要做一些配置工作即可實現 JDBC 認證。

    JDBC 認證方法支持多種數據庫,DB2, Oracle, MySql, Microsoft SQL Server 等均可,這里以 DB2 作為例子介紹。并且假設DB2數據庫名: CASTest,數據庫登錄用戶名: db2user,數據庫登錄密碼: db2password,用戶信息表為: userTable,該表包含用戶名和密碼的兩個數據項分別為 userName 和 password。

    1. 配置 DataStore

    打開文件 %CATALINA_HOME%/webapps/cas/WEB-INF/deployerConfigContext.xml,添加一個新的 bean 標簽,對于 DB2,內容如清單 4 所示:


    清單 4. 配置 DataStore
                    
    <bean id="casDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName">
    <value>com.ibm.db2.jcc.DB2Driver</value>
    </property>
    <property name="url">
    <value>jdbc:db2://9.125.65.134:50000/CASTest</value>
    </property>
    <property name="username">
    <value>db2user</value>
    </property>
    <property name="password">
    <value>db2password</value>
    </property>
    </bean>


    其中 id 屬性為該 DataStore 的標識,在后面配置 AuthenticationHandler 會被引用,另外,需要提供 DataStore 所必需的數據庫驅動程序、連接地址、數據庫登錄用戶名以及登錄密碼。

    2. 配置 AuthenticationHandler

    在 cas-server-support-jdbc-3.1.1.jar 包中,提供了 3 個基于 JDBC 的 AuthenticationHandler,分別為 BindModeSearchDatabaseAuthenticationHandler, QueryDatabaseAuthenticationHandler, SearchModeSearchDatabaseAuthenticationHandler。其中 BindModeSearchDatabaseAuthenticationHandler 是用所給的用戶名和密碼去建立數據庫連接,根據連接建立是否成功來判斷驗證成功與 否;QueryDatabaseAuthenticationHandler 通過配置一個 SQL 語句查出密碼,與所給密碼匹配;SearchModeSearchDatabaseAuthenticationHandler 通過配置存放用戶驗證信息的表、用戶名字段和密碼字段,構造查詢語句來驗證。

    使用哪個 AuthenticationHandler,需要在 deployerConfigContext.xml 中設置,默認情況下,CAS 使用一個簡單的 username=password 的 AuthenticationHandler,在文件中可以找到如下一行:<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePassword
    AuthenticationHandler" />,我們可以將其注釋掉,換成我們希望的一個 AuthenticationHandler,比如,使用QueryDatabaseAuthenticationHandler 或 SearchModeSearchDatabaseAuthenticationHandler 可以分別選取清單 5 或清單 6 的配置。


    清單 5. 使用 QueryDatabaseAuthenticationHandler
                    
    <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
    <property name="dataSource" ref=" casDataSource " />
    <property name="sql"
    value="select password from userTable where lower(userName) = lower(?)" />
    </bean>


    清單 6. 使用 SearchModeSearchDatabaseAuthenticationHandler
                    
    <bean id="SearchModeSearchDatabaseAuthenticationHandler"
    class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler"
    abstract="false" singleton="true" lazy-init="default"
    autowire="default" dependency-check="default">
    <property name="tableUsers">
    <value>userTable</value>
    </property>
    <property name="fieldUser">
    <value>userName</value>
    </property>
    <property name="fieldPassword">
    <value>password</value>
    </property>
    <property name="dataSource" ref=" casDataSource " />
    </bean>


    另外,由于存放在數據庫中的密碼通常是加密過的,所以 AuthenticationHandler 在匹配時需要知道使用的加密方法,在 deployerConfigContext.xml 文件中我們可以為具體的 AuthenticationHandler 類配置一個 property,指定加密器類,比如對于 QueryDatabaseAuthenticationHandler,可以修改如清單7所示:


    清單 7. 添加 passwordEncoder
                    
    <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
    <property name="dataSource" ref=" casDataSource " />
    <property name="sql"
    value="select password from userTable where lower(userName) = lower(?)" />
    <property name="passwordEncoder" ref="myPasswordEncoder"/>
    </bean>


    其中 myPasswordEncoder 是對清單 8 中設置的實際加密器類的引用:


    清單 8. 指定具體加密器類
                    
    <bean id="passwordEncoder"
    class="org.jasig.cas.authentication.handler.MyPasswordEncoder"/>

    這里 MyPasswordEncoder 是根據實際情況自己定義的加密器,實現 PasswordEncoder 接口及其 encode() 方法。

    3. 部署依賴包

    在以上配置完成以后,需要拷貝幾個依賴的包到 cas 應用下,包括:

    • 將 cas-server-support-jdbc-3.1.1.jar 拷貝到 %CATALINA_HOME%/webapps/cas/ WEB-INF/lib 目錄。
    • 數 據庫驅動,由于這里使用 DB2,將 %DB2_HOME%/java 目錄下的 db2java.zip (更名為 db2java.jar), db2jcc.jar, db2jcc_license_cu.jar 拷貝到 %CATALINA_HOME%/webapps/cas/WEB-INF/lib 目錄。對于其他數據庫,同樣將相應數據庫驅動程序拷貝到該目錄。
    • DataStore 依賴于 commons-collections-3.2.jar, commons-dbcp-1.2.1.jar, commons-pool-1.3.jar,需要到 apache 網站的 Commons 項目下載以上 3 個包放進 %CATALINA_HOME%/webapps/cas/WEB-INF/lib 目錄。

    擴展 CAS Server 界面

    CAS 提供了 2 套默認的頁面,分別為“ default ”和“ simple ”,分別在目錄“ cas/WEB-INF/view/jsp/default ”和“ cas/WEB-INF/view/jsp/simple ”下。其中 default 是一個稍微復雜一些的頁面,使用 CSS,而 simple 則是能讓 CAS 正常工作的最簡化的頁面。

    在部署 CAS 之前,我們可能需要定制一套新的 CAS Server 頁面,添加一些個性化的內容。最簡單的方法就是拷貝一份 default 或 simple 文件到“ cas/WEB-INF/view/jsp ”目錄下,比如命名為 newUI,接下來是實現和修改必要的頁面,有 4 個頁面是必須的:

    • casConfirmView.jsp: 當用戶選擇了“ warn ”時會看到的確認界面
    • casGenericSuccess.jsp: 在用戶成功通過認證而沒有目的Service時會看到的界面
    • casLoginView.jsp: 當需要用戶提供認證信息時會出現的界面
    • casLogoutView.jsp: 當用戶結束 CAS 單點登錄系統會話時出現的界面

    CAS 的頁面采用 Spring 框架編寫,對于不熟悉 Spring 的使用者,在修改之前需要熟悉該框架。

    頁面定制完過后,還需要做一些配置從而讓 CAS 找到新的頁面,拷貝“ cas/WEB-INF/classes/default_views.properties ”,重命名為“ cas/WEB-INF/classes/ newUI_views.properties ”,并修改其中所有的值到相應新頁面。最后是更新“ cas/WEB-INF/cas-servlet.xml ”文件中的 viewResolver,將其修改為如清單 9 中的內容。


    清單 9. 指定 CAS 頁面
                    
    <bean id="viewResolver"
    class="org.springframework.web.servlet.view.ResourceBundleViewResolver" p:order="0">
    <property name="basenames">
    <list>
    <value>${cas.viewResolver.basename}</value>
    <value> newUI_views</value>
    </list>
    </property>
    </bean>





    回頁首


    部署客戶端應用

    單點登錄的目的是為了讓多個相關聯的應用使用相同的登錄過程,本文在講解過程中構造 2個簡單的應用,分別以 casTest1 和 casTest2 來作為示例,它們均只有一個頁面,顯示歡迎信息和當前登錄用戶名。這 2 個應用使用同一套登錄信息,并且只有登錄過的用戶才能訪問,通過本文的配置,實現單點登錄,即只需登錄一次就可以訪問這兩個應用。

    與 CAS Server 建立信任關系

    假設 CAS Server 單獨部署在一臺機器 A,而客戶端應用部署在機器 B 上,由于客戶端應用與 CAS Server 的通信采用 SSL,因此,需要在 A 與 B 的 JRE 之間建立信任關系。

    首先與 A 機器一樣,要生成 B 機器上的證書,配置 Tomcat 的 SSL 協議。其次,下載http://blogs.sun.com/andreas/entry/no_more_unable_to_find 的 InstallCert.java,運行“ java InstallCert compA:8443 ”命令,并且在接下來出現的詢問中輸入 1。這樣,就將 A 添加到了 B 的 trust store 中。如果多個客戶端應用分別部署在不同機器上,那么每個機器都需要與 CAS Server 所在機器建立信任關系。

    配置 CAS Filter

    準備好應用 casTest1 和 casTest2 過后,分別部署在 B 和 C 機器上,由于 casTest1 和casTest2,B 和 C 完全等同,我們以 casTest1 在 B 機器上的配置做介紹,假設 A 和 B 的域名分別為 domainA 和 domainB。

    將 cas-client-java-2.1.1.zip 改名為 cas-client-java-2.1.1.jar 并拷貝到 casTest1/WEB-INF/lib目錄下,修改 web.xml 文件,添加 CAS Filter,如清單 10 所示:


    清單 10. 添加 CAS Filter
                    
    <web-app>
    ...
    <filter>
    <filter-name>CAS Filter</filter-name>
    <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>
    <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
    <param-value>https://domainA:8443/cas/login</param-value>
    </init-param>
    <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
    <param-value>https://domainA:8443/cas/serviceValidate</param-value>
    </init-param>
    <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
    <param-value>domainB:8080</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>CAS Filter</filter-name>
    <url-pattern>/protected-pattern/*</url-pattern>
    </filter-mapping>
    ...
    </web-app>


    對于所有訪問滿足 casTest1/protected-pattern/ 路徑的資源時,都要求到 CAS Server 登錄,如果需要整個 casTest1 均受保護,可以將 url-pattern 指定為“/*”。

    從清單 10 可以看到,我們可以為 CASFilter 指定一些參數,并且有些是必須的,表格 1表格 2 中分別是必需和可選的參數:


    表格 1. CASFilter 必需的參數
    參數名 作用
    edu.yale.its.tp.cas.client.filter.loginUrl 指定 CAS 提供登錄頁面的 URL
    edu.yale.its.tp.cas.client.filter.validateUrl 指定 CAS 提供 service ticket 或 proxy ticket 驗證服務的 URL
    edu.yale.its.tp.cas.client.filter.serverName 指定客戶端的域名和端口,是指客戶端應用所在機器而不是 CAS Server 所在機器,該參數或 serviceUrl 至少有一個必須指定
    edu.yale.its.tp.cas.client.filter.serviceUrl 該參數指定過后將覆蓋 serverName 參數,成為登錄成功過后重定向的目的地址


    表格 2. CASFilter 可選參數
    參數名 作用
    edu.yale.its.tp.cas.client.filter.proxyCallbackUrl 用于當前應用需要作為其他服務的代理(proxy)時獲取 Proxy Granting Ticket 的地址
    edu.yale.its.tp.cas.client.filter.authorizedProxy 用 于允許當前應用從代理處獲取 proxy tickets,該參數接受以空格分隔開的多個 proxy URLs,但實際使用只需要一個成功即可。當指定該參數過后,需要修改 validateUrl 到 proxyValidate,而不再是 serviceValidate
    edu.yale.its.tp.cas.client.filter.renew 如果指定為 true,那么受保護的資源每次被訪問時均要求用戶重新進行驗證,而不管之前是否已經通過
    edu.yale.its.tp.cas.client.filter.wrapRequest 如果指定為 true,那么 CASFilter 將重新包裝 HttpRequest,并且使 getRemoteUser() 方法返回當前登錄用戶的用戶名
    edu.yale.its.tp.cas.client.filter.gateway 指定 gateway 屬性

    傳遞登錄用戶名

    CAS 在登錄成功過后,會給瀏覽器回傳 Cookie,設置新的到的 Service Ticket。但客戶端應用擁有各自的 Session,我們要怎么在各個應用中獲取當前登錄用戶的用戶名呢?CAS Client 的 Filter 已經做好了處理,在登錄成功后,就可以直接從 Session 的屬性中獲取,如清單 11 所示:


    清單 11. 在 Java 中通過 Session 獲取登錄用戶名
                    
    // 以下兩者都可以
    session.getAttribute(CASFilter.CAS_FILTER_USER);
    session.getAttribute("edu.yale.its.tp.cas.client.filter.user");


    在 JSTL 中獲取用戶名的方法如清單 12 所示:


    清單 12. 通過 JSTL 獲取登錄用戶名
                    
    <c:out value="${sessionScope[CAS:'edu.yale.its.tp.cas.client.filter.user']}"/>

    另外,CAS 提供了一個 CASFilterRequestWrapper 類,該類繼承自HttpServletRequestWrapper,主要是重寫了 getRemoteUser() 方法,只要在前面配置 CASFilter 的時候為其設置“ edu.yale.its.tp.cas.client.filter.wrapRequest ”參數為 true,就可以通過 getRemoteUser() 方法來獲取登錄用戶名,具體方法如清單 13 所示:


    清單 13. 通過 CASFilterRequestWrapper 獲取登錄用戶名
                    
    CASFilterRequestWrapper reqWrapper=new CASFilterRequestWrapper(request);
    out.println("The logon user:" + reqWrapper.getRemoteUser());





    回頁首


    效果

    在 casTest1 和 casTest2 中,都有一個簡單 Servlet 作為歡迎頁面 WelcomPage,且該頁面必須登錄過后才能訪問,頁面代碼如清單 14 所示:


    清單 14. WelcomePage 頁面代碼
                    
    public class WelcomePage extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head>");
    out.println("<title>Welcome to casTest2 sample System!</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>Welcome to casTest1 sample System!</h1>");
    CASFilterRequestWrapper reqWrapper=new CASFilterRequestWrapper(request);
    out.println("<p>The logon user:" + reqWrapper.getRemoteUser() + "</p>");
    HttpSession session=request.getSession();
    out.println("<p>The logon user:" +
    session.getAttribute(CASFilter.CAS_FILTER_USER) + "</p>");
    out.println("<p>The logon user:" +
    session.getAttribute("edu.yale.its.tp.cas.client.filter.user") + "</p>");
    out.println("</body>");
    out.println("</html>");
    }
    }


    在上面所有配置結束過后,分別在 A, B, C上啟動 cas, casTest1 和 casTest2,按照下面步驟來訪問 casTest1 和 casTest2:

    1. 打開瀏覽器,訪問 http://domainB:8080/casTest1/WelcomePage ,瀏覽器會彈出安全提示,接受后即轉到 CAS 的登錄頁面,如圖 2 所示:

    圖 2. CAS 登錄頁面
    CAS 登錄頁面
    1. 登錄成功后,再重定向到 casTest1 的 WelcomePage 頁面,如所示:

    圖 3. 登錄后訪問 casTest1 的效果
    登錄后訪問 casTest1 的效果

    可以看到中地址欄里的地址多出了一個 ticket 參數,這就是 CAS 分配給當前應用的 ST(Service Ticket)。

    1. 再在同一個瀏覽器的地址欄中輸入 http://domainC:8080/casTest2/WelcomePage ,系統不再提示用戶登錄,而直接出現如圖 4 所示的頁面,并且顯示在 casTest1 中已經登錄過的用戶。

    圖 4. 在 casTest1 中登錄過后訪問 casTest2 的效果
    在 casTest1 中登錄過后訪問 casTest2 的效果
    1. 重新打開一個瀏覽器窗口,先輸入 http://domainC:8080/casTest2/WelcomePage ,系統要求登錄,在登錄成功過后,正確顯示 casTest2 的頁面。之后再在地址欄重新輸入 http://domainB:8080/casTest1/WelcomePage ,會直接顯示 casTest1 的頁面而無需再次登錄。




    回頁首


    結束語

    本文介紹了 CAS 單點登錄解決方案的原理,并結合實例講解了在 Tomcat 中使用 CAS 的配置、部署方法以及效果。CAS 是作為開源單點登錄解決方案的一個不錯選擇,更多的使用細節可以參考 CAS 官方網站。



    參考資料

    轉自:IBM開發者社區


    名稱: ?4C.ESL | .↗Evon
    口號: 遇到新問題?先要尋找一個方案乄而不是創造一個方案こ
    mail: 聯系我


    主站蜘蛛池模板: 亚洲AV无码专区亚洲AV桃| 男女做羞羞的事视频免费观看无遮挡| 亚洲综合AV在线在线播放| 国产精品入口麻豆免费观看| 男男gay做爽爽的视频免费| 亚洲一区二区三区国产精品无码| 亚洲欧洲日产国码无码久久99 | 亚洲 综合 国产 欧洲 丝袜 | 久久久亚洲裙底偷窥综合| 亚洲一本大道无码av天堂| 永久在线毛片免费观看| 噼里啪啦免费观看高清动漫4 | 亚洲美女中文字幕| 亚洲成a人片77777kkkk| 在线a亚洲v天堂网2019无码| 四虎永久免费网站免费观看| 国产精品美女午夜爽爽爽免费| 91青青青国产在观免费影视| 中文字幕无码免费久久| 亚洲精品成人网站在线播放| 亚洲最大免费视频网| 永久在线观看免费视频| eeuss免费天堂影院| 永久免费无码网站在线观看个| 亚洲成在人线在线播放无码| 国产精品亚洲专区在线观看 | 亚洲一区免费观看| A片在线免费观看| 成人无码区免费A∨直播| 国产高清对白在线观看免费91| 本道天堂成在人线av无码免费| 三级片免费观看久久| 高清免费久久午夜精品| 老司机精品视频免费| 免费国产在线精品一区| 一区二区视频在线免费观看| 一进一出60分钟免费视频| A级毛片成人网站免费看| 日本免费久久久久久久网站| 国产午夜不卡AV免费| 久久国产色AV免费看|