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

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

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

    herodby
    技術 筆記
    posts - 14,  comments - 14,  trackbacks - 0
    CAS技術框架

    CAS Server
    目前,我們使用的CAS Server 3.1.1的是基于Spring Framework編寫的,因此在CAS服務器端的配置管理中,絕大多數是Spring式的Java Bean XML配置。CAS 的服務器提供了一套易于定制的用戶認證器接口,用戶可以根據自身企業(yè)的在線系統(tǒng)的認證方式,來定制自己的認證邏輯。不論是傳統(tǒng)的用戶名/密碼方式,還是基于安全證書的方式;是基于關系數據庫的存儲,還是采用LDAP服務器,CAS Server給我們提供了這些常用的驗證器模板代碼,只要稍作修改,便可靈活使用了。
    對于廣大的中國企業(yè)用戶而言,另一個需要定制的功能莫過于全中文、企業(yè)特色的用戶身份認證頁面了。CAS Server提供了兩套系統(tǒng)界面,一套是默認的CAS英文標準頁面,另一套則是專門提供給用戶來定制修改的。(PS:老外們做事情就是人性化啊~~)那么對CAS Server端的后續(xù)學習,我們將圍繞著身份認證模塊定制和界面定制這兩方面展開。

    CAS Client
    客戶端我們使用的是CAS Client 2.1.1。雖然在官方網站上已出現了3.1.0版本的下載,但該版本地代碼已經完全重寫,使用的package和類名同2.1.1大相徑庭了,最關鍵的是,該版本暫時沒有對應的API說明文檔。雖然咖啡我對程序版本懷有極大的“喜新厭舊”的心態(tài),但安全起見,還是先2.1.1吧,相信3.1.0的文檔耶魯大學的大牛們已經在整理了,期待中……
    CAS Client2.1.1.jar中的代碼是相當精煉的,有興趣的朋友建議閱讀一下源碼。Jar包中的代碼分成三個大部分
    1. edu.yale.its.tp.cas.util 包,其中只有一個工具類 SecureURL.java 用來訪問HTTPS URL
    2. edu.yale.its.tp.cas.proxy包,用來處理Proxy Authentication代理認證的3個類,其中ProxyTicketReceptor.java是 接收PGT回調的servlet,在下文中我們會提及。
    3. edu.yale.its.tp.cas.client包,其中包含了CAS Filter ,Tag Library等主要的認證客戶端工具類,我們在后面會進行重點介紹。
    針對CAS Client的學習,我們的重點將放在CAS Filter 和ProxyTicketReceptor 的配置以及在Java SE環(huán)境下,直接使用 ServiceTicketValidator進行Ticket認證實現上。

    CAS服務器端應用
    定制適合你的身份認證程序
    通過前面的學習,我們了解了CAS具有一個良好而強大的SSO功能框架。接下來,我們要學習如何將實際企業(yè)應用中的身份認證同CAS進行整合。
    簡單的說,要將現有企業(yè)應用中的認證集成到CAS Server中,只要實現一個名為AuthenticationHandler的一個認證處理Java接口就行。以下是該接口的源代碼:
    Java代碼 復制代碼
    1. public interface AuthenticationHandler {   
    2. /**  
    3. * 該方法決定一個受支持的credentials是否是可用的,  
    4. * 如果可用,該方法返回true,則說明身份認證通過  
    5. */  
    6. boolean  authenticate(Credentials credentials)  throws  AuthenticationException;   
    7. /**  
    8. * 該方法決定一個credentials是否是當前的handle所支持的  
    9. */  
    10. boolean  supports(Credentials credentials);   
    11. }  

    這里我們要說明一下Credentials這個CAS的概念。所謂Credentials是由外界提供給CAS來證明自身身份的信息,簡單的如一個用戶名/密碼對就是一個Credentials,或者一個經過某種加密算法生成的密文證書也可以是一個Credentials。在程序的實現上,Credentials被聲明為一個可序列化的接口,僅僅起著標識作用,源代碼如下:
    Java代碼 復制代碼
    1. public interface Credentials extends Serializable {   
    2.     // marker interface contains no methods   
    3. }  

    CAS的API中,已經為我們提供了一個最常用的實現UsernamePasswordCredentials 用戶名/密碼憑證,代碼如下:
    Java代碼 復制代碼
    1. public class UsernamePasswordCredentials implements Credentials {   
    2.     /** Unique ID for serialization. */  
    3.     private static final long serialVersionUID = -8343864967200862794L;   
    4.     /** The username. */  
    5.     private String username;   
    6.     /** The password. */  
    7.     private String password;   
    8.     public final String getPassword() {   
    9.         return this.password;   
    10.     }   
    11.     public final void setPassword(final String password) {   
    12.         this.password = password;   
    13.     }   
    14.     public final String getUsername() {   
    15.         return this.username;   
    16.     }   
    17.     public final void setUsername(final String userName) {   
    18.         this.username = userName;   
    19.     }   
    20.     public String toString() {   
    21.         return this.username;   
    22.     }   
    23.     public boolean equals(final Object obj) {   
    24.         if (obj == null || !obj.getClass().equals(this.getClass())) {   
    25.             return false;   
    26.         }   
    27.         final UsernamePasswordCredentials c = (UsernamePasswordCredentials) obj;   
    28.         return this.username.equals(c.getUsername())   
    29.             && this.password.equals(c.getPassword());   
    30.     }   
    31.     public int hashCode() {   
    32.         return this.username.hashCode() ^ this.password.hashCode();   
    33.     }   
    34. }  

    很簡單不是嗎?就是存儲一個用戶名和密碼的java bean而已。
    接下來,我們將一個Credentials傳給一個AuthenticationHandler進行認證,首先調用boolean supports(Credentials credentials)方法察看當前傳入的Credentials實例,AuthenticationHandler實例現是否支持它?如果支持,再調用boolean authenticate(Credentials credentials)方法進行認證。由于用戶名/密碼方式是最常用的認證方法,因此CAS為我們提供了一個現成的基于該方式的抽象認證處理類AbstractUsernamePasswordAuthenticationHandler。通常我們只需要繼承該類,并實現其中的 authenticateUsernamePasswordInternal方法即可。下面我們給出一個Demo的實現類,它的校驗邏輯很簡單——僅校驗用戶名的字符長度是否與密碼的相等(這里密碼是一個表示長度的整數),如果相等則認為認證通過,請看代碼:
    Java代碼 復制代碼
    1. public class UsernameLengthAuthnHandler   
    2.                        extends AbstractUsernamePasswordAuthenticationHandler {   
    3. protected boolean authenticateUsernamePasswordInternal( UsernamePasswordCredentials credentials)  throws AuthenticationException {   
    4. /*   
    5. * 這里我們完全可以用自己的認證邏輯代替,比如將用戶名/密碼傳入一個SQL語句   
    6. * 向數據庫驗證是否有對應的用戶賬號,這不是我們最經常干的事么?   
    7. * 只需要將下面的程序替換掉就OK了?。o  easy,so  simple!   
    8. /   
    9.     String username = credentials.getUsername();   
    10.     String password = credentials.getPassword();   
    11.     String correctPassword = Integer.toString(username.length());   
    12.     return correctPassword.equals(password);   
    13. }   
    14. }  

    介紹到這里,大家應該清楚如何定制自己的AuthenticationHandler類了吧!這里要附帶說明的是,在CAS Server的擴展API中已經提供了大量常用認證形式的實現類,它們同CAS Server的war包一同分發(fā):
    cas-server-support-generic-3.1.1.jar ——使用Map記錄用戶認證信息的實現
    cas-server-support-jdbc-3.1.1.jar —— 基于Spring JDBC的數據庫實現(我們常用的)
    cas-server-support-ldap-3.1.1.jar —— 基于LDAP的用戶認證實現
    更多其他形式的實現各位看官有興趣的,可以一一閱讀源碼。

    配置你的身份認證程序
    完成了定制認證類的代碼編寫,接下來就是要讓CAS Server來調用它了。在CAS的框架中,對程序的配置都是使用Spring Framework的xml文件,這對于熟悉Spring的程序員而言算駕輕就熟了。
    配置文件位于應用部署目錄的WEB-INF子目錄下——deployerConfigContext.xml。在bean id=authenticationManager 的 authenticationHandlers屬性中配置我們的AuthenticationHandlers:
    引用

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean id="authenticationManager"
    class="org.jasig.cas.authentication.AuthenticationManagerImpl">
    。。。
    。。。
    <property name="authenticationHandlers">
    <list>
    <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" />
    <!—下面就是系統(tǒng)默認的驗證器配置,你可以替換它,或者增加一個新的handler -->
    <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
    </list>
    </property>
    </bean>
    。。。
    。。。
    </beans>

    我們發(fā)現authenticationHandlers屬性是一個list,在這個list中可以配置多個AuthenticationHandlers。這些AuthenticationHandlers形成了一個驗證器鏈,所有提交給CAS的Credentials信息將通過這個驗證器鏈的鏈式過濾,只要這鏈中有一個驗證器通過了對Credentials的驗證,就認為這個Credentials是合法的。這樣的設計使得我們可以很輕松的整合不同驗證體系的已有應用到同一個CAS上,比如:A驗證器負責校驗alpha系統(tǒng)提交的Credentials,它是基于LDAP服務器的;B驗證器負責校驗beta系統(tǒng)提交的Credentials,它是一個傳統(tǒng)的RDB用戶表認證;C驗證器負責校驗gamma系統(tǒng)提交的基于RSA證書加密的Credentials。3種完全不同的用戶身份認證通過配置就可以統(tǒng)一在同一個CAS服務內,很好很強大,不是嗎??!

    定制身份驗證登錄界面
    CAS Server在顯示界面層view使用了“主題Theme”的概念。在{project.home}/webapp/WEB-INF/view/jsp/目錄下,系統(tǒng)默認提供了兩套得UI —— default和simple 。default方案使用了CSS等相對復雜得界面元素,而simple方案提供了最簡化的界面表示方式。在整個的CAS Server服務器端,有四個界面是我們必須要實現的:
    casConfirmView.jsp —— 確認信息(警告信息)頁面
    casGenericSuccess.jsp —— 登陸成功提示頁面
    casLoginView.jsp —— 登錄輸入頁面
    casLogoutView.jsp —— SSO登出提示頁面
    這些都是標準的jsp頁面,如何實現他們,完全由您說了算,除了名字不能改。

    CAS為view的展示提供了3個級別的定制方式,讓我們從最直觀簡單的開始吧。

    1. 采用文件覆蓋方式:直接修改default中的頁面或者將新寫好的四個jsp文件覆蓋到default目錄中。這種方式最直觀和簡單,但咖啡建議各位在使用這種方式前將原有目錄中的文件備份一下,以備不時之需。

    2. 修改UI配置文件,定位UI目錄:在CAS Server端/webapp/WEB-INF/classes/ 目錄下,有一個名為default_views.properties的屬性配置文件,你可以通過修改配置文件中的各個頁面文件位置,指向你新UI文件,來達到修改頁面展示的目的。

    3. 修改配置文件的配置文件,這話看起來有點別扭,其實一點不難理解。在方法2中的default_views.properties文件是一整套的UI頁面配置。如果我想保存多套的UI頁面配置就可以寫多個的properties文件來保存這些配置。在CAS Server端/webapp/WEB-INF/目錄下有cas-servlet.xml和cas.properties兩個文件,cas-servlet.xml使用了cas.properties文件中的cas.viewResolver.basename屬性來定義view屬性文件的名字,因此你可以選者直接修改cas-servlet.xml中的viewResolver 下的basenames屬性,或者修改cas.properties中的cas.viewResolver.basename屬性,指定新的properties文件名,這樣可以輕松的替換全套UI。

    CAS客戶端配置及API應用
    CASFilter的配置
    對于大部分web應用而言,使用CAS集成統(tǒng)一認證是相對簡單的事,只要為需要認證的URL配置edu.yale.its.tp.cas.client.filter.CASFilter認證過濾器。下面我們就針對過濾器的配置進行說明。首先參看一下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://secure.its.yale.edu/cas/login<;/param-value>
    </init-param>
    <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
    <param-value>https://secure.its.yale.edu/cas/serviceValidate<;/param-value>
    </init-param>
    <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
    <param-value>your server name and port (e.g., www.yale.edu:8080)</param-value>
    </init-param>
    </filter>

    <filter-mapping>
    <filter-name>CAS Filter</filter-name>
    <url-pattern>/requires-cas-authetication/*</url-pattern>
    </filter-mapping>
    ...
    </web-app>

    上述配置中的init-param是filter的3個必備的屬性,下面這張表則是filter全部屬性的詳細說明:


    ProxyTicketReceptor的配置
    大家還記得在前面我們說過的Proxy Authentication中的call back URL嗎?ProxyTicketReceptor是部署在client端的一個servlet,提供server端回傳PGT和PGTIOU的。它的xml部署如下:
    引用

    <web-app>
    ...
    <servlet>
    <servlet-name>ProxyTicketReceptor</servlet-name>
    <servlet-class>edu.yale.its.tp.cas.proxy.ProxyTicketReceptor</servlet-class>
    <init-param>
    <param-name>edu.yale.its.tp.cas.proxyUrl</param-name>
    <param-value>https://secure.its.yale.edu/cas/proxy<;/param-value>
    </init-param>
    </servlet>

    <servlet-mapping>
    <servlet-name>ProxyTicketReceptor</servlet-name>
    <url-pattern>/CasProxyServlet</url-pattern>
    </servlet-mapping>
    ...
    </webapp>


    這里要說明的是它的參數edu.yale.its.tp.cas.proxyUrl。在服務端通過ProxyTicketReceptor將PGT和PGTIOU傳給客戶端后,ProxyTicketReceptor在進行Proxy Authentication的過程中需要向服務端請求一個ProxyTicket(PT),這個proxyUrl就是服務端的請求入口了。(關于Proxy Authentication的運作原理,參見JA-SIG(CAS)學習筆記2

    CAS Client端的API應用1.用戶可以通過以下兩種方式的任意一種,從JSP或servlet中獲取通過認證的用戶名:
    引用
    String username = (String)session.getAttribute(CASFilter.CAS_FILTER_USER);
    或者
    String username = (String)session.getAttribute("edu.yale.its.tp.cas.client.filter.user");


    2.獲得更完整的受認證用戶信息對象CASReceipt Java Bean,可以使用以下語句的任一:
    引用
    CASReceipt receipt = (CASReceipt )session.getAttribute(CASFilter.CAS_FILTER_RECEIPT);
    或者
    CASReceipt receipt = (CASReceipt )session.getAttribute("edu.yale.its.tp.cas.client.filter.receipt");


    3.手工編碼使用CAS Java Object進行用戶驗證,使用ServiceTicketValidator或者 ProxyTicketValidator(代理認證模式下),在servlet中對用戶身份進行驗證。
    3-1.ServiceTicketValidator
    Java代碼 復制代碼
    1. import edu.yale.its.tp.cas.client.*;    
    2.  ...   
    3.  String user = null;   
    4.  String errorCode = null;   
    5.  String errorMessage = null;   
    6.  String xmlResponse = null;   
    7.     
    8.  /* instantiate a new ServiceTicketValidator */  
    9.  ServiceTicketValidator sv = new ServiceTicketValidator();   
    10.     
    11.  /* set its parameters */  
    12.  sv.setCasValidateUrl("https://secure.its.yale.edu/cas/serviceValidate");   
    13.  sv.setService(urlOfThisService);   
    14.  sv.setServiceTicket(request.getParameter("ticket"));    
    15.     
    16.  String urlOfProxyCallbackServlet = "https://portal.yale.edu/CasProxyServlet";    
    17.  sv.setProxyCallbackUrl(urlOfProxyCallbackServlet);   
    18.     
    19.  /* contact CAS and validate */  
    20.  sv.validate();   
    21.     
    22.  /* if we want to look at the raw response, we can use getResponse() */  
    23.  xmlResponse = sv.getResponse();   
    24.     
    25.  if(sv.isAuthenticationSuccesful()) {   
    26.   user = sv.getUser();   
    27.  } else {   
    28.   errorCode = sv.getErrorCode();   
    29.   errorMessage = sv.getErrorMessage();   
    30.  }   
    31.   /* The user is now authenticated. */  
    32.   /* If we did set the proxy callback url, we can get proxy tickets with: */  
    33.   String urlOfTargetService = "http://hkg2.its.yale.edu/someApp/portalFeed";   
    34.   String proxyTicket = ProxyTicketReceptor.getProxyTicket( sv.getPgtIou() , urlOfTargetService);  


    3-2.ProxyTicketValidator
    Java代碼 復制代碼
    1. import edu.yale.its.tp.cas.client.*;   
    2.  ...    
    3.  String user = null;   
    4.  String errorCode = null;   
    5.  String errorMessage = null;   
    6.  String xmlResponse = null;   
    7.  List proxyList = null;   
    8.     
    9.  /* instantiate a new ProxyTicketValidator */  
    10.  ProxyTicketValidator pv = new ProxyTicketValidator();    
    11.     
    12.  /* set its parameters */  
    13.  pv.setCasValidateUrl("https://secure.its.yale.edu/cas/proxyValidate");   
    14.  pv.setService(urlOfThisService);   
    15.  pv.setServiceTicket(request.getParameter("ticket"));    
    16.     
    17.  String urlOfProxyCallbackServlet = "https://portal.yale.edu/CasProxyServlet";   
    18.  pv.setProxyCallbackUrl(urlOfProxyCallbackServlet);    
    19.     
    20.  /* contact CAS and validate */  
    21.  pv.validate();   
    22.     
    23.  /* if we want to look at the raw response, we can use getResponse() */  
    24.  xmlResponse = pv.getResponse();    
    25.     
    26.  /* read the response */  
    27.  if(pv.isAuthenticationSuccesful()) {   
    28.   user = pv.getUser();   
    29.   proxyList = pv.getProxyList();   
    30.  } else {   
    31.   errorCode = pv.getErrorCode();   
    32.   errorMessage = pv.getErrorMessage();   
    33.   /* handle the error */  
    34.  }    
    35.  /* The user is now authenticated. */    
    36.  /* If we did set the proxy callback url, we can get proxy tickets with this method call: */    
    37.  String urlOfTargetService = "http://hkg2.its.yale.edu/someApp/portalFeed";    
    38.  String proxyTicket = ProxyTicketReceptor.getProxyTicket( pv.getPgtIou() , urlOfTargetService);  


    在這里,我們假設上下文環(huán)境中的用戶已經通過了CAS登錄認證,被重定向到當前的servlet下,我們在servlet中獲取ticket憑證,servlet的URL對用戶身份進行確認。如果上下文參數中無法獲取ticket憑證,我們就認為用戶尚未登錄,那么,該servlet必須負責將用戶重定向到CAS的登錄頁面去。
    posted on 2008-06-28 16:51 鄧兵野 閱讀(636) 評論(0)  編輯  收藏 所屬分類: sso單點登錄

    只有注冊用戶登錄后才能發(fā)表評論。


    網站導航:
     

    <2008年6月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    293012345

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 高潮毛片无遮挡高清免费| 亚洲AV无码久久精品狠狠爱浪潮| 亚洲一级在线观看| 最近中文字幕mv免费高清视频8| 亚洲国产成人片在线观看| 中出五十路免费视频| 国产精品视频免费一区二区三区| 亚洲人成网站18禁止| 免费鲁丝片一级观看| 精品久久亚洲一级α| 在线视频免费国产成人| 色婷婷亚洲一区二区三区| 久久久青草青青国产亚洲免观 | 3d动漫精品啪啪一区二区免费| 亚洲伊人tv综合网色| 99久久综合精品免费| 亚洲国产美女精品久久| 成年美女黄网站18禁免费| 亚洲综合色丁香婷婷六月图片| 成人免费福利电影| 黄床大片30分钟免费看| 亚洲综合亚洲综合网成人| 一级毛片无遮挡免费全部| 亚洲AV无码码潮喷在线观看 | 免费鲁丝片一级在线观看| 人妖系列免费网站观看| 久久久久亚洲精品美女| 性短视频在线观看免费不卡流畅| 亚洲熟妇AV乱码在线观看| 亚洲伊人久久成综合人影院| 久久综合给合久久国产免费| 亚洲国产精品一区二区三区在线观看| 国产一级高清视频免费看| 免费国产在线视频| 亚洲熟妇AV日韩熟妇在线| 亚洲男同帅GAY片在线观看| 成人免费激情视频| 人成电影网在线观看免费| 亚洲视频在线一区二区三区| 国产又粗又长又硬免费视频| 四虎国产精品永久免费网址|