天天看點

CAS單點登入(用戶端、服務端)搭建

一、單點登入簡介

單點登入(Single Sign On),簡稱為 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,使用者隻需要登入一次就可以通路所有互相信任的應用系統。

CAS 是一個開源的企業級單點登入系統,CAS 包含兩個部分:CAS Server 和 CAS Client,它們之間獨立部署。CAS 用戶端攔截未認證的使用者請求,并重定向至 CAS 服務端,由 CAS 服務端對使用者身份進行統一認證。

二、服務端搭建

對于搭建 CAS 服務端,CAS官方網站提供了基于 Maven 和 Gradle 的 Overlay 建構方式:具體見

1)Maven: https://github.com/apereo/cas-overlay-template

2)Gradle:https://github.com/apereo/cas-gradle-overlay-template

本文使用的是 CAS Maven WAR Overlay。Overlay 技術可以把多個項目 war 合并成為一個項目,如果項目存在同名檔案,那麼主項目中的檔案将覆寫掉其他項目的同名檔案。使用 Overlay 無需對 CAS 源碼進行編譯,也避免了對 CAS 源碼進行侵入性改造。

1、搭建環境

JDK 1.8

Tomcat 8.0+

IntelliJ IDEA 2017.2

2、OverLay建構

打開 Project Structure,可以觀察到該工程具有兩個 Web Root,但是 src/main/webapp 目錄并不存在,需要進行手動建立。

CAS單點登入(用戶端、服務端)搭建

拷貝 overlays 目錄下的 application.properties 配置檔案至 resources 目錄,用于覆寫 CAS WAR 中的同名檔案。最終工程目錄結構如下:

CAS單點登入(用戶端、服務端)搭建

啟動tomcat(可以内置或者外置),本文是使用了外置tomcat。

啟動成功後,通路 http://localhost:8080/cas/login 進入登入界面。

CAS單點登入(用戶端、服務端)搭建

注:

Non-secure Connection

提示需要配置 SSL,

Static Authentication

提示需要對使用者配置進行修改,可以修改為 JDBC、REST 等方式。

目前使用者配置寫死在 application.properties 配置檔案中,使用者名為 casuser,密碼為 Mellon。

3、配置services

用戶端接入 CAS 首先需要在服務端進行注冊,否則用戶端通路将提示“未認證授權的服務”警告。

在 resources 檔案夾下建立 services 檔案夾進行服務定義,該目錄中可包含多個 JSON 檔案,其命名必須滿足以下規則:

JSON fileName = serviceName + "-" + serviceNumericId + ".json"
           

建立 services/localhost-10000003.json 檔案,表示允許所有以 http://localhost 開頭的認證請求:

{
  "@class": "org.apereo.cas.services.RegexRegisteredService",
  "serviceId": "^(http)://localhost.*",
  "name": "localhost",
  "id": 10000003,
  "description": "這是一個本地允許的服務,通過localhost通路都允許通過",
  "evaluationOrder": 1
}
           

說明:

@class:必須為org.apereo.cas.services.RegisteredService的實作類

serviceId:對服務進行描述的表達式,可用于比對一個或多個 URL 位址

name: 服務名稱

id:全局唯一标志

evaluationOrder:定義多個服務的執行順序

然後修改application.properties 檔案告知 CAS 服務端從本地加載服務定義檔案

#開啟識别json檔案,預設false
cas.serviceRegistry.initFromJson=true
#自動掃描服務配置,預設開啟
#cas.serviceRegistry.watcherEnabled=true
#120秒掃描一遍
#cas.serviceRegistry.repeatInterval=120000
#延遲15秒開啟
#cas.serviceRegistry.startDelay=15000
#資源加載路徑
#cas.serviceRegistry.config.location=classpath:/services
           

重新啟動tomcat,出現如下日志,說明服務注冊成功。

2018-03-18 23:36:08,660 INFO [org.apereo.cas.services.AbstractServicesManager] - <Loaded [0] service(s) from [InMemoryServiceRegistry].>
2018-03-18 23:36:08,876 INFO [org.apereo.cas.config.CasServiceRegistryInitializationConfiguration] - <Attempting to initialize the service registry [InMemoryServiceRegistry] from service definition resources found at [class path resource [services]]>
2018-03-18 23:36:08,877 WARN [org.apereo.cas.services.ServiceRegistryInitializer] - <Service registry [InMemoryServiceRegistry] will be auto-initialized from JSON service definitions. This behavior is only useful for testing purposes and MAY NOT be appropriate for production. Consider turning off this behavior via the setting [cas.serviceRegistry.initFromJson=false] and explicitly register definitions in the services registry.>
2018-03-18 23:36:09,283 INFO [org.apereo.cas.services.AbstractServicesManager] - <Loaded [3] service(s) from [InMemoryServiceRegistry].>
           

三、搭建用戶端

CAS官方網站上有CAS-client的案例,見https://apereo.github.io/cas/5.2.x/integration/CAS-Clients.html

亦可參考:https://github.com/cas-projects/cas-sample-java-webapp,本文是參考了後者搭建的。

修改 pom.xml,修改 tomcat7-maven-plugin 設定通路位址為

http://localhost:8181/node1

<!--  tomcat7 plugin -->
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <port>8181</port>
        <uriEncoding>UTF-8</uriEncoding>
        <server>tomcat7</server>
        <path>/node1</path>
    </configuration>
</plugin>
           

CAS Client 通過攔截器将未認證的請求重定向到 CAS Server,這裡對 cas-sample-java-webapp 的 web.xml 檔案進行修改,将服務端、用戶端位址替換為實際測試的位址:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!--
   <context-param>
       <param-name>renew</param-name>
       <param-value>true</param-value>
   </context-param>
-->
    <!--單點登出過濾器-->
    <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://localhost:8080/cas</param-value>
        </init-param>
    </filter>

    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>

    <!--用來跳轉登入-->
    <filter>
        <filter-name>CAS Authentication Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class>-->
        <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:8181/node1</param-value>
        </init-param>
    </filter>

    <!--Ticket校驗過濾器-->
    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.validation.Saml11TicketValidationFilter</filter-class>-->
        <filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</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:8181/node1</param-value>
        </init-param>
        <init-param>
            <param-name>redirectAfterValidation</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>useSession</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>authn_method</param-name>
            <param-value>mfa-duo</param-value>
        </init-param>
    </filter>

    <!-- 該過濾器負責實作HttpServletRequest請求的包裹,比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置-->
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>

    <!-- 該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來擷取使用者的登入名。 比如AssertionHolder.getAssertion().getPrincipal().getName()-->
    <!--<filter>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>-->

    <filter-mapping>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <url-pattern>/*</url-pattern>
           

運作該tomcat,登入http://localhost:8081/node1,網頁如下:

CAS單點登入(用戶端、服務端)搭建

輸入密碼登入成功後的網頁如下:

CAS單點登入(用戶端、服務端)搭建

利用相同的方法配置第二個用戶端,通路位址為

http://localhost:8288/node2

,可知在 node1 登入成功的情況下,無需再次輸入使用者密碼即可通路 node2 背景頁面。

參考文章:

https://apereo.github.io/cas/5.2.x/installation/Maven-Overlay-Installation.html

https://segmentfault.com/a/1190000013844049

https://www.cnblogs.com/flying607/p/7600947.html

https://github.com/apereo/cas/tree/4.0.x

繼續閱讀