單點登錄CAS使用記(五):cas-client不攔截靜態資源以及無需登錄的請求。


一.問題在哪?

在配置cas-client中,有這么一段配置:

    <filter>
        <filter-name>CAS Filter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>https://demo.testcas.com/cas/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://app1.testcas.com</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

詳情請參考:單點登錄CAS使用記(二):部署CAS服務器以及客戶端

意思大概是:攔截客戶端的所有請求,如果發現還沒有通過CAS認證中心認證,則強行重定向到Cas-server的登錄頁面。

這里面有一個問題?

即:客戶端所有請求都被攔截並且跳轉,包括靜態資源,靜態頁面等,這是不合理的。

 

二.如何解決?

2.1 百度下大多數的解決方案

擴展CASFilter過濾器,加上一個排除指定URL的功能,然后在web.xml配置中,手動添加需要排除的所有URL。

這確是一種解決方法,但是過於繁瑣,而且在網站請求地址過多的情況下,稍有不慎,就會出現遺漏。

如果這是你想要的,請另行百度。

 

2.2 我的解決方案:

因為我是要整合兩個比較成熟的項目,換言之,就是這兩個項目已經自帶了用戶登錄驗證、用戶權限驗證、不攔截靜態資源等處理。

所以我是不是可以利用原有項目的攔截邏輯?

原有項目功能簡述:

1.項目采用了SpringMVC框架

2.對所有靜態資源放行,例如:css、js、img等

例如:web.xml中配置如下(激活Tomcat的defaultServlet來處理靜態文件

<servlet-mapping>  
  <servlet-name>default</servlet-name> 
  <url-pattern>*.jpg</url-pattern>   
</servlet-mapping>  
<servlet-mapping>    
  <servlet-name>default</servlet-name>
  <url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>default</servlet-name>    
  <url-pattern>*.css</url-pattern>
</servlet-mapping>

3.自定義了一個@RequestSecurity的注解,並對所有有權限控制的方法加上該注解

4.用戶發出請求->被攔截器攔截->攔截器判斷該用戶請求方法是否被標注了@RequestSecurity

   IF:如果有該注解,繼續判斷用戶是否已經登錄(通過session是否存在來判斷),如果沒有登錄,則重定向到登錄頁面進行登錄。

   ELSE:如果沒有該注解,證明該資源可隨意訪問,直接放行。

注意上文紅色描述,所以,我只要稍微改造一下原有項目的攔截器,讓他不是直接跳轉到原有登錄頁面,跳轉到一個特定的請求地址,讓cas-filter攔截只攔截這一個請求就可以了。

 

三.改造驗證

第一步:修改原有項目攔截器

項目中,有這么一段SpringMVC攔截器配置(偽代碼展示)

    <mvc:interceptors>
        <bean class="com.xxxx.interceptor.SecurityInterceptor">
            <property name="redirectUrl">
                <value>/login</value>
            </property>
       ...
        </bean>
    </mvc:interceptors>

意思就是,一旦攔截到用戶未登錄,直接跳轉到doLogin方法,讓用戶登錄。

我對他修改如下:

    <mvc:interceptors>
        <bean class="com.xxxx.interceptor.SecurityInterceptor">
            <property name="redirectUrl">
                <value>/casLogin</value>
            </property>
       ...
        </bean>
    </mvc:interceptors>

意思就是:一旦攔截到用戶未登錄,跳轉到doCasLogin方法

 

第二步:新增casLogin方法

    @RequestSecurity
    @RequestMapping(value = "casLogin", method = { RequestMethod.GET,
            RequestMethod.POST })
    public String casLogin()
    {
        return "welcome";
    }

意思就是:如果用戶未登錄,會被強制重定向到本方法。

 

第三步:修改cas-client的攔截器Cas-Filter的攔截范圍

    <filter>
        <filter-name>CAS Filter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>https://demo.testcas.com/cas/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://app1.testcas.com</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Filter</filter-name>
        <url-pattern>/casLogin</url-pattern>
    </filter-mapping>

意思就是:CAS Filter只攔截casLogin請求,其他請求一律不攔截。一旦攔截到casLogin請求,說明用戶暫未登錄,則強制重定向到Cas-Server的登錄頁面。

到這里,Cas-client不攔截靜態資源處理就改造好了。

 

但是,如果只做上面3步,進行測試的話,瀏覽器有可能會報“此頁面包含重定向循環”的錯誤提示,並不能真正登入頁面。

原因看以下流程:

1.首先被重定向到了Cas認證中心

2.用戶輸入用戶名密碼等,點擊登錄通過了Cas登陸認證

3.再一次被重定向回/casLogin,

4.又被Cas-Fliter攔截,不過此時Cas-Fliter發現用戶已經通過了Cas認證中心認證,不做重定向處理,繼續后續處理。

5.因為casLogin方法標注了@RequestSecurity,所以又被原有項目的mvc:interceptors攔截,攔截器發現用戶未登錄(通過session是否為空來判斷)

6.又被強行重定向會casLogin,然后又回到了4陷入了無窮的循環中...

 

如何打破此重定向循環?

關鍵在於第5步,當Cas-Server重定向回來時,會帶回通過認證的用戶信息。

取得方式如下:

AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
String username = principal.getName();

這時,在過濾器判斷用戶是否已經登錄前,先行判斷如果是Cas-server重定向過來的請求,並且principal、username存在,則把用戶信息寫入客戶端UserSession中。

然后再判斷發現,已經寫入了UserSession了,說明登錄成功,直接登錄welcome頁面。

 

登錄成功。

 

注:本文所記錄的是自己摸索所得,並不敢完全保證程序邏輯的嚴謹性,如果您發現有所紕漏,請給予批評指正。

 


單點登錄CAS使用記系列:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM