黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

Cas(07)——建立使用Cas進行單點登錄的應用

系統 1935 0

建立使用 Cas 進行單點登錄的應用

?

目錄

1.1 加入 cas-client-core-xxx.jar classpath

1.2 配置 Filter

1.2.1 AuthenticationFilter

1.2.2 TicketValidationFilter

1.2.3 HttpServletRequestWrapperFilter

1.2.4 AssertionThreadLocalFilter

1.2.5 基于 Spring Filter 配置

1.3 添加證書到信任庫

?

?????? 根據之前的描述我們知道, Cas 由兩部分組成, Cas Server Cas Client Cas Server Cas 自己的服務端,而 Cas Client Cas 客戶端,其需要與我們自己的應用進行集成。

?

1.1 ???? 加入 cas-client-core-xxx.jar classpath

?????? 在我們下載的 Cas Client 壓縮包的 modules 目錄下可以找到一個名為 cas-client-core-xxx.jar jar 文件,首先需要將該 jar 包加入我們應用的類路徑下,筆者這里使用的是 cas-client-core-3.1.11.jar 。如果用戶的應用是使用 Maven 構造的,則可以在應用的 pom.xml 文件中加入如下依賴。

?? < dependency >

????? < groupId > org.jasig.cas.client </ groupId >

????? < artifactId > cas -client-core </ artifactId >

????? < version > 3.1.11 </ version >

?? </ dependency >

?

1.2 ???? 配置 Filter

?????? 然后需要我們在應用的 web.xml 文件中配置四個 Filter ,這四個 Filter 必須按照固定的順序來進行配置,而且它們必須配置在應用的其它 Filter 之前。它們的先后順序要求如下:

l ? AuthenticationFilter

l ? TicketValidationFilter

l ? HttpServletRequestWrapperFilter

l ? AssertionThreadLocalFilter

?

?????? 這些 Filter 有的必須指定某些參數,有的可以指定某些參數,這些參數可以通過 context-param 來指定,也可以通過 init-param 來指定。 Cas Client 默認會先從 init-param 取,沒取到則從 context-param 取,所以當 init-param context-param 都指定了某個參數時, init-param 指定的將擁有更高的優先級。所以當多個 Filter 需要共用一個參數時,我們可以把它定義為 context-param

?

1.2.1 ??? AuthenticationFilter

?????? AuthenticationFilter 用來攔截所有的請求,用以判斷用戶是否需要通過 Cas Server 進行認證,如果需要則將跳轉到 Cas Server 的登錄頁面。如果不需要進行登錄認證,則請求會繼續往下執行。

???? AuthenticationFilter 有兩個用戶必須指定的參數,一個是用來指定 Cas Server 登錄地址的 casServerLoginUrl ,另一個是用來指定認證成功后需要跳轉地址的 serverName service service serverName 只需要指定一個就可以了。當兩者都指定了,參數 service 將具有更高的優先級,即將以 service 指定的參數值為準。 service serverName 的區別在于 service 指定的是一個確定的 URL ,認證成功后就會確切的跳轉到 service 指定的 URL ;而 serverName 則是用來指定主機名,其格式為 {protocol}:{hostName}:{port} ,如: https://localhost:8443 ,當指定的是 serverName 時, AuthenticationFilter 將會把它附加上當前請求的 URI ,以及對應的查詢參數來構造一個確定的 URL ,如指定 serverName 為“ http://localhost ”,而當前請求的 URI 為“ /app ”,查詢參數為“ a=b&b=c ”,則對應認證成功后的跳轉地址將為“ http://localhost/app?a=b&b=c ”。

?

?????? 除了上述必須指定的參數外, AuthenticationFilter 還可以指定如下可選參數:

l ? renew :當指定 renew true 時,在請 Cas Server 時將帶上參數“ renew=true ”,默認為 false

l ? gateway :指定 gateway true 時,在請求 Cas Server 時將帶上參數“ gateway=true ”,默認為 false

l ? artifactParameterName :指定 ticket 對應的請求參數名稱,默認為 ticket

l ? serviceParameterName :指定 service 對應的請求參數名稱,默認為 service

?

?????? 如下是一個配置 AuthenticationFilter 的示例, serverName 由于在接下來配置的 Filter 中還要用,所以利用 context-param 將其配置為一個公用的參數。“ elim ”對應我的電腦名。

?

?? < context-param >

????? < param-name > serverName </ param-name >

????? < param-value > http://elim:8080 </ param-value >

?? </ context-param >

??

?? < filter >

????? < filter-name > casAuthenticationFilter </ filter-name >

?? < filter-class > org.jasig.cas.client.authentication.AuthenticationFilter </ filter-class >

????? < init-param >

???????? < param-name > casServerLoginUrl </ param-name >

???????? < param-value > https://elim:8443/cas/login </ param-value >

????? </ init-param >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casAuthenticationFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

1.2.2 ??? TicketValidationFilter

?????? 在請求通過 AuthenticationFilter 的認證之后,如果請求中攜帶了參數 ticket 則將會由 TicketValidationFilter 來對攜帶的 ticket 進行校驗。 TicketValidationFilter 只是對驗證 ticket 的這一類 Filter 的統稱,其并不對應 Cas Client 中的一個具體類型。 Cas Client 中有多種驗證 ticket Filter ,都繼承自 AbstractTicketValidationFilter ,它們的驗證邏輯都是一致的,都有 AbstractTicketValidationFilter 實現,所不同的是使用的 TicketValidator 不一樣。筆者這里將以 Cas10TicketValidationFilter 為例,其它還有 Cas20ProxyReceivingTicketValidationFilter Saml11TicketValidationFilter

?

?? < filter >

????? < filter-name > casTicketValidationFilter </ filter-name >

?? < filter-class > org.jasig.cas.client.validation.Cas10TicketValidationFilter </ filter-class >

????? < init-param >

???????? < param-name > casServerUrlPrefix </ param-name >

???????? < param-value > https://elim:8443/cas </ param-value >

????? </ init-param >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casTicketValidationFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

?????? 必須指定的參數:

l ? casServerUrlPrefix :用來指定 Cas Server 對應 URL 地址的前綴,如上面示例的“ https://elim:8443/cas ”。

l ? serverName service :語義跟前面介紹的一致。

?

?????? 可選參數:

l ? redirectAfterValidation ? :表示是否驗證通過后重新跳轉到該 URL ,但是不帶參數 ticket ,默認為 true

l ? useSession ? :在驗證 ticket 成功后會生成一個 Assertion 對象,如果 useSession true ,則會將該對象存放到 Session 中。如果為 false ,則要求每次請求都需要攜帶 ticket 進行驗證,顯然 useSession false redirectAfterValidation true 是沖突的。默認為 true

l ? exceptionOnValidationFailure ? :表示 ticket 驗證失敗后是否需要拋出異常,默認為 true

l ? renew :當值為 true 時將發送“ renew=true ”到 Cas Server ,默認為 false

?

1.2.3 ??? HttpServletRequestWrapperFilter

?????? HttpServletRequestWrapperFilter 用于將每一個請求對應的 HttpServletRequest 封裝為其內部定義的 CasHttpServletRequestWrapper ,該封裝類將利用之前保存在 Session request 中的 Assertion 對象重寫 HttpServletRequest getUserPrincipal() getRemoteUser() isUserInRole() 方法。這樣在我們的應用中就可以非常方便的從 HttpServletRequest 中獲取到用戶的相關信息。以下是一個配置 HttpServletRequestWrapperFilter 的示例:

?? < filter >

????? < filter-name > casHttpServletRequestWrapperFilter </ filter-name >

?? < filter-class > org.jasig.cas.client.util.HttpServletRequestWrapperFilter </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casHttpServletRequestWrapperFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

1.2.4 ??? AssertionThreadLocalFilter

?????? AssertionThreadLocalFilter 是為了方便用戶在應用的其它地方獲取 Assertion 對象,其會將當前的 Assertion 對象存放到當前的線程變量中,那么以后用戶在程序的任何地方都可以從線程變量中獲取當前 Assertion ,無需再從 Session request 中進行解析。該線程變量是由 AssertionHolder 持有的,我們在獲取當前的 Assertion 時也只需要通過 AssertionHolder getAssertion() 方法獲取即可,如:

?? Assertion assertion = AssertionHolder. getAssertion ();

?

?????? AssertionThreadLocalFilter 這種設計理念是非常好的,實際應用中使用的也比較多, Spring Security 中也有用到這種理念。為了便于大家了解,特貼出 AssertionHolder 的源碼如下:

public? class AssertionHolder {

?

??? /**

???? * ThreadLocal to hold the Assertion for Threads to access.

???? */

??? private? static? final ThreadLocal threadLocal = new ThreadLocal();

?

?

??? /**

???? * Retrieve the assertion from the ThreadLocal.

???? */

??? public? static Assertion getAssertion() {

??????? return (Assertion) threadLocal .get();

??? }

?

??? /**

???? * Add the Assertion to the ThreadLocal.

???? */

??? public? static? void setAssertion( final Assertion assertion) {

??????? threadLocal .set(assertion);

??? }

?

??? /**

???? * Clear the ThreadLocal.

???? */

??? public? static? void clear() {

??????? threadLocal .set( null );

??? }

}

?

?????? 以下是配置 AssertionThreadLocalFilter 的示例:

?? < filter >

????? < filter-name > casAssertionThreadLocalFilter </ filter-name >

?? ? < filter-class > org.jasig.cas.client.util.AssertionThreadLocalFilter </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casAssertionThreadLocalFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

1.2.5 ??? 基于Spring的Filter配置

?????? 使用 Cas 單點登錄的應用需要我們在應用的 web.xml 文件中配置上述介紹的四個 Filter ,但如果用戶的應用是使用 Spring 開發的,則我們可以只在 web.xml 文件中配置四個 Spring DelegatingFilterProxy 用來代理需要配置的四個 Filter ,對應的 Filter 名稱對應我們需要代理的 Spring ApplicationContext bean 的名稱,此時我們需要將對應的 Filter 配置為 Spring ApplicationContext 中的一個 bean 對象。所以此時對應的 web.xml 文件的定義應該是這樣的:

?? < filter >

????? < filter-name > casAuthenticationFilter </ filter-name >

?? ? < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casAuthenticationFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

?? < filter >

????? < filter-name > casTicketValidationFilter </ filter-name >

?? ? < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casTicketValidationFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

?? < filter >

????? < filter-name > casHttpServletRequestWrapperFilter </ filter-name >

?? ? < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casHttpServletRequestWrapperFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

?? < filter >

????? < filter-name > casAssertionThreadLocalFilter </ filter-name >

?? ? < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >

?? </ filter >

?? < filter-mapping >

????? < filter-name > casAssertionThreadLocalFilter </ filter-name >

????? < url-pattern > /* </ url-pattern >

?? </ filter-mapping >

?

?????? 而對應的 Filter 應該都以對應的名稱定義為 Spring ApplicationContext 中的一個 bean

?? < bean name = "casAuthenticationFilter"

????? class = "org.jasig.cas.client.authentication.AuthenticationFilter"

????? p:casServerLoginUrl = "https://elim:8443/cas/login" p:renew = "false"

????? p:gateway = "false" p:serverName = "http://elim:8080" />

?

?? < bean name = "casTicketValidationFilter"

????? class = "org.jasig.cas.client.validation.Cas10TicketValidationFilter"

????? p:serverName = "http://elim:8080" p:redirectAfterValidation = "true" >

????? < property name = "ticketValidator" >

???????? < bean class = "org.jasig.cas.client.validation.Cas10TicketValidator" >

??????????? <!-- 對應于 casServerUrlPrefix -->

??????????? < constructor-arg index = "0" value = "https://elim:8443/cas" />

???????? </ bean >

????? </ property >

?? </ bean >

?

?? < bean id = "casHttpServletRequestWrapperFilter" class = "org.jasig.cas.client.util.HttpServletRequestWrapperFilter" />

??

?? < bean id = "casAssertionThreadLocalFilter" class = "org.jasig.cas.client.util.AssertionThreadLocalFilter" />

?

1.3 ???? 添加證書到信任庫

?????? ticket 驗證成功后,還需要驗證證書,這需要我們將之前建立的證書導出并添加到當前 JRE 的證書信任庫中,否則將驗證失敗。 JRE 在尋找證書時將根據當前使用的 host 來尋找,且會用該 host 匹配之前創建證書時指定的用戶名稱,如果匹配則表示找到。這也就意味著我們在 創建證書時指定的用戶名稱需要是我們的 host 。我的機器名稱為“ elim ”,我就把它作為我的 host ,那么對應的證書應該這樣創建。

keytool -genkey -keyalg RSA -alias tomcat -dname "cn=elim" -storepass changeit

?

?????? 該語句是對我們之前介紹的 keytool -genkey -alias tomcat -keyalg RSA 的精寫,它已經通過相應的參數指定了對應的參數值,而不需要再與用戶交互了。如果還用之前的語句生成證書的話,那么對應的值應該這樣填:


Cas(07)——建立使用Cas進行單點登錄的應用
?

?

?????? 之后會在用戶的對應目錄下生成一個 .keystore 文件。之后需要將該文件導出為一個證書到 %JAVA_HOME%/jre/lib/security 目錄下,對應指令為:

keytool -export -alias tomcat -file %JAVA_HOME%/jre/lib/security/tomcat.crt -storepass changeit

?

?????? 之后需要將導出的 tomcat.crt 證書添加到運行時使用的 JRE 的受信任證書庫中,此時如果出現異常可將原本 %JAVA_HOME%/jre/lib/security 目錄下的 cacerts 刪除后繼續執行以下指令。

keytool -import -alias tomcat -file %JAVA_HOME%/jre/lib/security/tomcat.crt -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit

?

?????? 經過以上幾步后就可以啟用我們自己的 Cas Client 應用了,然后初次訪問該應用時就會跳轉到 Cas Server 進行登錄認證。認證成功后將跳轉到我們自己的 Client 應用進行 ticket 的驗證,驗證通過后就可以自由的訪問我們的 Client 應用了。

?

(注:本文是基于 Cas Server3.5.2 Cas Client3.1.11 所寫)

(注:原創文章,轉載請注明出處。原文地址: http://haohaoxuexi.iteye.com/blog/2142631

?

?

?

Cas(07)——建立使用Cas進行單點登錄的應用


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論