1. 程式人生 > >SSO(Single Sign On)系列(三)--CAS單點登入

SSO(Single Sign On)系列(三)--CAS單點登入

上篇文章介紹了SSO的原理以及5種基本流程,相信看完了之後不難理解單點登入,而CASSSO的一種實現方案,原理是一樣的。下面介紹一下。

CAS Server:負責完成對使用者的認證工作,需要獨立部署,CAS Server會處理使用者名稱/密碼等憑證。

CAS Client:負責處理對客戶端受保護資源的訪問請求,需要對請求方進行身份認證時,重定向到CAS Server進行認證。CASClient與受保護的客戶端應用部署在一起,以Filter方式保護受保護資源。

CAS請求認證圖


說明:CAS Client與受保護的客戶端應用部署在一起,以Filter方式保護Web應用的受保護資源,過濾從客戶端過來的每一個

web請求,同時,CAS Client會分析HTTP請求中是否包含請求Service Ticket,如果沒有,則說明該使用者是沒有經過認證的;於是CAS Client會重新定向到CASServer(傳遞Service<要訪問的資源地址>+cookie)。CAS Server驗證TGT失敗返回登入頁面。輸入認證資訊,如果Credentials認證資訊成功,CAS Server隨機產生一個相當長度、唯一、不可偽造的Service Ticket,並快取以待將來驗證,並重定向到Service所在地址,併為客戶端瀏覽器設定一個Ticket Granted Cookie;Cas Client
在拿到Service和新產生的Ticket過後,在CAS Server進行驗證,驗證成功後,進行快取。

經過分析發現,CAS請求認證圖和上篇文章的SSO認證圖是大同小異的。

例項

       兩個CAS Client實現單點登入效果,登入進去之後顯示更多的驗證資訊:(以tomcat中的示例example為例做測試)

       伺服器:tomcat 6.0

一、CAS Server部署

       解壓cas-server-3.5.2-release.zip(提取cas-server-3.5.2-release.zip\cas-server-3.5.2\modules\cas-server-webapp-3.5.2.war

,重新命名為cas.war)部署到tomcat中。

二、CAS Client配置:

 1、\WEB-INF\lib下新增jar

    cas-client-core-3.2.0(cas-client-3.2.0-release.zip解壓提取cas-client-3.2.0/modules/cas-client-core-3.2.0

commons-logging-1.1.1

2web.xml配置攔截器(client1為例)

 <listener>
                       <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
                </listener>
<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
                <filter>
                        <filter-name>CASSingle Sign Out Filter</filter-name>
                       <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
                </filter>
                <filter-mapping>
                        <filter-name>CASSingle 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>
                               <param-value>http://localhost:8080/cas/login</param-value>
                        </init-param>
                        <init-param>
                               <param-name>serverName</param-name>
                               <param-value>http://localhost:18080</param-value>
                        </init-param>
                </filter>
                <filter-mapping>
                        <filter-name>CASFilter</filter-name>
                       <url-pattern>/*</url-pattern>
                </filter-mapping>
                <!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 -->
                <filter>
                        <filter-name>CASValidation Filter</filter-name>
                        <filter-class>
                               org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
                        <init-param>
                               <param-name>casServerUrlPrefix</param-name>
                               <param-value>http://localhost:8080/cas</param-value>
                        </init-param>
                        <init-param>
                               <param-name>serverName</param-name>
                               <param-value>http://localhost:18080</param-value>
                        </init-param>
                </filter>
                <filter-mapping>
                        <filter-name>CASValidation Filter</filter-name>
                       <url-pattern>/*</url-pattern>
                </filter-mapping>
<!--
                        該過濾器負責實現HttpServletRequest請求的包裹,
                        比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置。
                -->
                <filter>
                        <filter-name>CASHttpServletRequest Wrapper Filter</filter-name>
                        <filter-class>
                               org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
                </filter>
                <filter-mapping>
                        <filter-name>CASHttpServletRequest Wrapper Filter</filter-name>
                       <url-pattern>/*</url-pattern>
                </filter-mapping>
<!--
                該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取使用者的登入名。
                比如AssertionHolder.getAssertion().getPrincipal().getName()。
                -->
                <filter>
                        <filter-name>CASAssertion Thread Local Filter</filter-name>
                       <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
                </filter>
                <filter-mapping>
                        <filter-name>CASAssertion Thread Local Filter</filter-name>
                       <url-pattern>/*</url-pattern>
                </filter-mapping>

3、同理在client2web.xml配置同上,注意修改埠號

4、頁面顯示更多的憑證資訊

程式碼:HelloWorldExample.java裡面新增程式碼:

Assertion assertion = (Assertion)request.getSession().getAttribute(
               AbstractCasFilter.CONST_CAS_ASSERTION);
if (null != assertion){
        out.println(" Log | ValidFromDate=:"
                        +assertion.getValidFromDate() + "<br>");
        out.println(" Log | ValidUntilDate=:"
                        +assertion.getValidUntilDate() + "<br>");
        Map<String, Object> attMap =assertion.getAttributes();
        out.println(" Log | getAttributesMap size = " + attMap.size()
                        +"<br>");
        for (Entry<String, Object> entry: attMap.entrySet()) {
                out.println("     | " + entry.getKey() + "=:"
                                +entry.getValue() + "<br>");
        }
        AttributePrincipal principal =assertion.getPrincipal();
//AttributePrincipalprincipal = (AttributePrincipal) request
        // .getUserPrincipal();
String username = null;
        out.print(" Log |UserName:");
        if (null != principal) {
                username = principal.getName();
                out.println("<spanstyle='color:red;'>" + username
                                +"</span><br>");
        }
}

5、測試驗證:

輸入client1網址:http://localhost:18080/examples/servlets/servlet/HelloWorldExample

跳轉到登入頁面:


輸入使用者名稱,密碼:admin,admin

跳轉頁面


看返回地址,在這裡返回一個STclient端,快取起來。

接著訪問client2,網址:http://localhost:28080/examples/servlets/servlet/HelloWorldExample,不用輸入使用者名稱和密碼,跳轉到client2的業務頁面:


看輸入連結,只有本地的連結

原理:根據Cookie驗證是否已經登入

       注:如果訪問有問題,則修改安全認證的安全級別,cas預設的是HTTPS協議,如果對安全的要求不高,可使用HTTP協議。

        修改預設協議如下:

        修改deployerConfigContext.xml 增加引數p:requireSecure="false",是否需要安全驗證,即HTTPS,false為不採用。

<beanclass="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"p:httpClient-ref="httpClient"
p:requireSecure="false"/>
 
       修改ticketGrantingTicketCookieGenerator.xml(cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml) 中ticketGrantingTicketCookieGenerator p:cookieSecure 屬性 修改為 false。
       <beanid="ticketGrantingTicketCookieGenerator"class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="false"p:cookieMaxAge="-1" p:cookieName="CASTGC"p:cookiePath="/cas" />

總結

通過cas,系統之間解耦,並且不用開發人員再單獨去開發資訊認證系統,統一的資訊管理平臺,大大簡化了開發。

附原始碼