CAS搭建及簡單Demo實現單點登錄

CAS搭建及簡單Demo實現單點登錄

環境

  • ubuntu server 16.04LTS
  • docker 19.03.3
  • cas v5.3.x
  • JDK 1.8
  • Gradle 4.10

本地搭建

拉取倉庫並部署運行

It is recommended to build and deploy CAS locally using the WAR Overlay method. 
This approach does not require the adopter to explicitly download any version of CAS, 
but rather utilizes the overlay mechanism to combine CAS original artifacts and local 
customizations to further ease future upgrades and maintenance.
  • 拉取倉庫
$ git clone https://github.com/apereo/cas-overlay-template/tree/5.3
  • 切換分支
    該倉庫下最新的版本的6.0的,接下來的操作都在5.3的基礎上進行測試,這裏先切換下分支
$ git checkout 5.3
  • 打包
$ mvn clean package

看到下面的日誌表示打包成功

[INFO] --- maven-war-plugin:2.6:war (default-war) @ cas-overlay ---
[INFO] Packaging webapp
[INFO] Assembling webapp [cas-overlay] in [D:\cloud\cas-overlay-template\target\cas]
[info] Copying manifest...
[INFO] Processing war project
[INFO] Processing overlay [ id org.apereo.cas:cas-server-webapp-tomcat]
[INFO] Webapp assembled in [1981 msecs]
[INFO] Building war: D:\cloud\cas-overlay-template\target\cas.war
[INFO]
[INFO] --- spring-boot-maven-plugin:1.5.18.RELEASE:repackage (default) @ cas-overlay ---
[INFO] Layout: WAR
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
  • 運行
    • 運行採用外部tomcat的方式,下載tomcat的安裝包,要求版本8.5+。
    • 將上一步生成的cas-overlay-template\target\cas.war拷貝到tomcat的webapp下,啓動tocmat。等應用程序啓動成功後,打開瀏覽器輸入http://localhost:8080/cas/login即可進入登錄頁面
      在這裏插入圖片描述
  • 登錄
    默認情況下,CAS採用靜態的用戶名密碼登錄,固定爲默認賬號/默認密碼:casuser/Mellon,在apache-tomcat-8.5.47\webapps\cas\WEB-INF\classes\application.properties文件的最下方,能看到
##
# CAS Authentication Credentials
#
cas.authn.accept.users=casuser::Mellon

輸入用戶名密碼後即可成功登錄
在這裏插入圖片描述

去除登錄頁面的警告框

默認情況下,登錄頁面右側有兩個警告框,如下圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9ZJclrjL-1583071140312)(003_images/cas_login_page_warn.png)]
其中大概含義如下:

- 不安全的連接:您正在使用不安全的方式連接到CAS,SSO服務將無法正常使用,如果想要正常使用SSO服務,請使用HTTPS登錄
- 靜態身份認證:cas被配置爲接受用於主身份驗證的靜態用戶列表。注意,這隻適用於測試程序。建議將cas連接到ldap、jdbc等。

解決方式如下:

啓用SSL

  • 生成證書

官方提供的cas-overlay-template下可以執行

# Windows
$ build.cmd gencert
# Linux
$ sh build.sh gencert

注意,這裏使用官方提供的gencert的命令,生成的證書並不在項目目錄下,以我本地爲例,執行命令後生成的keystore在D:\etc\cas\thekeystore下,密碼爲changeit,可在build.cmd中查看到

  • 配置tomcat
    編輯tomcat目錄下/conf/server.xml,修改其中的節點
 <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="D:\etc\cas\thekeystore"
                         type="RSA" certificateKeystoreType="JKS" certificateKeystorePassword="changeit" />
        </SSLHostConfig>
    </Connector>

其中certificateKeystoreFile爲上一步生成的keystore的目錄,certificateKeystorePassword爲keystore的密碼,這些參數都可在build.cmd中查看到,下面是build.cmd執行gencert命令時的一部分命令

 $ keytool -genkeypair -alias cas -keyalg RSA -keypass changeit -storepass changeit -keystore %CAS_DIR%\thekeystore -dname %DNAME% -ext SAN=%CERT_SUBJ_ALT_NAMES%

以上步驟完成後,啓動tomcat,在瀏覽器中輸入https://127.0.0.1:8443/cas/login,會進入登錄頁面,因爲證書時自簽發的證書,不被瀏覽器信任,所以會顯示不安全的提示,但是警告框已經沒有了,如下圖所示
在這裏插入圖片描述

認證

使用JDBC方式登錄

使用明文方式保存密碼

官方文檔
從上圖可知,雖然已經沒了SSL的安全登錄問題,但還是有靜態用戶認證的問題,根據提示可以修改成LDAPJDBC等登錄方式。這裏我們使用JDBC的方式登錄。使用JDBC的登錄方式,需要覆蓋默認策略。這裏在官方提供的cas-overlay-template基礎上進行開發。

  • 創建項目結構
    在項目cas-overlay-template的根目錄下,新建文件夾,結構如下
cas-overlay-template
   |----etc
   |----maven
   |----src
       |----main
           |----java
           |----resource
   *******

在前面步驟中啓動了tomcat將cas.war自動解壓,將apache-tomcat-8.5.47\webapps\cas\WEB-INF\classes下的application.properties拷貝到上一步的resource文件夾下
前面提到過,在application.properties文件的最後一行配置了固定的用戶名和密碼,這裏將這行註釋掉。

  • 引入依賴
    通過JDBC的方式,需要引入相關的依賴。下面的方式可以引入所有數據庫的驅動,相對來說可能比較耗時
        <!--
        ...Additional dependencies may be placed here...
        -->
        <!--新增支持jdbc驗證-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-jdbc</artifactId>
            <version>${cas.version}</version>
        </dependency>

        <!--若不想找驅動可以直接寫下面的依賴即可,其中包括HSQLDB、Oracle、MYSQL、PostgreSQL、MariaDB、Microsoft SQL Server-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-jdbc-drivers</artifactId>
            <version>${cas.version}</version>
        </dependency>

注意:添加的依賴可能會有很多衝突,可以使用MAVEN HELPER插件排除有衝突的依賴

  • 創建數據庫和表
字段名 字段類型 備註
id bigint ID
username varchar 用戶名
password varchar 用戶密碼
expired bigint 是否過期,1爲過期,需修改密碼
disabled bigint 是否啓用,1爲不可用,禁用
CREATE DATABASE `cas`;
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `expired` int(11) DEFAULT NULL,
  `disabled` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', 'root', 'root', '0', '0');
  • 配置文件增加數據庫配置


##
# CAS Authentication Credentials
#
#cas.authn.accept.users=casuser::Mellon
#查詢賬號密碼SQL,必須包含密碼字段
cas.authn.jdbc.query[0].sql=select * from tb_user where username=?

#指定上面的SQL查詢字段名(必須)
cas.authn.jdbc.query[0].fieldPassword=password

#指定過期字段,1爲過期,若過期不可用
cas.authn.jdbc.query[0].fieldExpired=expired

#爲不可用字段段,1爲不可用,需要修改密碼
cas.authn.jdbc.query[0].fieldDisabled=disabled

#數據庫連接
cas.authn.jdbc.query[0].url=jdbc:mysql://127.0.0.1:3306/cas?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8

#數據庫dialect配置
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect

#數據庫用戶名
cas.authn.jdbc.query[0].user=root

#數據庫用戶密碼
cas.authn.jdbc.query[0].password=root

#數據庫事務自動提交
cas.authn.jdbc.query[0].autocommit=false

#數據庫驅動
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver

#超時配置
cas.authn.jdbc.query[0].idleTimeout=5000

#默認加密策略,通過encodingAlgorithm來指定算法,默認NONE不加密
cas.authn.jdbc.query[0].passwordEncoder.type=NONE
#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
  • 打包和部署
    1.重新執行mvn clean package,將target/cas.war拷貝到tomcat的webapps下,覆蓋原來的文件,並刪除cas文件夾
    2.啓動tomcat,啓動成功後打開瀏覽器輸入https://127.0.0.1:8443/cas/login,如下圖所示
    在這裏插入圖片描述
    3.使用數據庫中的數據
    在這裏插入圖片描述
    4.root/root,即可成功登錄
    在這裏插入圖片描述

使用密文方式保存密碼

常用單向加密算法:MD5、SHA、HMAC。

一般我們常用的加密算法就這幾種。在JDBC認證中我們也可以選擇配置加密算法,加密算法一般爲上面的三種,MD5、SHA、HMAC,加密類型爲NONE|DEFAULT|STANDARD|BCRYPT|SCRYPT|PBKDF2這幾種,我們在配置文件中選擇加密類型,指定加密算法。修改配置文件,增加以下內容:


#默認加密策略,通過encodingAlgorithm來指定算法,默認NONE不加密
# NONE|DEFAULT|STANDARD|BCRYPT|SCRYPT|PBKDF2
cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
# 字符類型
cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
# 加密算法
cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
# 加密鹽
#cas.authn.jdbc.query[0].passwordEncoder.secret=
# 加密字符長度
#cas.authn.jdbc.query[0].passwordEncoder.strength=16

將數據庫中的密碼(password)字段改爲經過md5摘要後的值(root/root)
在這裏插入圖片描述
使用root/root登錄到系統,登錄成功!

自定義認證策略

除此之外如果我們要自定義加密類型,就需要實現org.springframework.security.crypto.password.PasswordEncoder接口,並且把類名配置在passwordEncoder.type。下面是實現一個用sm3摘要並以十六進制保存密碼的自定義認證策略

public class KlCASPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        // charSequence爲輸入的用戶密碼
        //HashUtil爲工具類,可自行修改成其他
        return HashUtil.sm3AndHex(rawPassword.toString());
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        // 當encode方法返回不爲null時,matches方法纔會調用,charSequence爲encode返回的字符串
        // str字符串爲數據庫中密碼字段返回的值
        if(rawPassword == null){
            return false;
        }
        if(HashUtil.sm3AndHex(rawPassword.toString()).equals(encodedPassword)){
            return true;
        }
        return false;
    }
}

application.properties中修改下面內容,將認證類型指定成自定義的類

cas.authn.jdbc.query[0].passwordEncoder.type=koal.cas.pwd.KlCASPasswordEncoder

將數據庫中的密碼(password)字段的值,改爲root進行sm3摘要後的十六進制字符串
在這裏插入圖片描述
啓動替換cas.war後重啓tomcat,或java -jar cas.war,進入登錄頁面,使用root/root登錄,能夠登錄成功。

白名單認證

CAS同時也支持白名單認證方式,主要是File和JSON格式

  • 白名單
    pom.xml中添加依賴
<dependency>
  <groupId>org.apereo.cas</groupId>
  <artifactId>cas-server-support-generic</artifactId>
  <version>${cas.version}</version>
</dependency>

application.properties中添加配置

##
# 白名單——file配置
#
cas.authn.file.separator=::
cas.authn.file.filename=file:///D:/etc/cas/white
cas.authn.file.name=

white文件中增加下面內容

test::test

重新打包,並啓動cas.war,進入登錄頁面,使用test/test登錄,結果如下:
在這裏插入圖片描述

黑名單認證

application.peroperties中增加配置

##
# 黑名單配置
#
cas.authn.reject.users=test,anumbrella
cas.authn.reject.name=

當不在黑名單中的用戶,就會全部接受,用戶甚至亂輸入密碼都可實現登錄。
同樣的如果我們要配置密碼加密,更改配置文件如下:

#默認加密策略,通過encodingAlgorithm來指定算法,默認NONE不加密
# NONE|DEFAULT|STANDARD|BCRYPT|SCRYPT|PBKDF2
cas.authn.reject.passwordEncoder.type=NONE
# 字符類型
# cas.authn.reject.passwordEncoder.characterEncoding=UTF-8
# 加密算法
# cas.authn.reject.passwordEncoder.encodingAlgorithm=MD5

新增一個用戶名密碼爲test1/root的用戶,重新打包,並啓動cas.war,進入登錄頁面,使用test1登錄,結果如下:

rest 官方文檔連接

官方文檔的最上面,有一段提示:
在這裏插入圖片描述
意思是說,通過接口的方式進行單點登錄的操作。REST這種方式是解決驗證數據不在CAS服務端,而是在本地端。

這裏的Rest認證就是指通過數據接口(第三方服務)對用戶進行認證,通過發起一個POST請求來進行認證。 當用戶點擊登錄後,CAS會發送POST請求到認證服務端。在請求頭中包含一個Authorization認證,裏面的值爲Basic XYZ,而這個XYZ就是通過Base64編碼後的用戶信息。
比如:
若輸入用戶名密碼爲:koal/123
那麼請求頭包括:
authorization=Basic Base64(koal:123)
如果登錄成功響應200,返回響應中包含id和attributes字段,如下:

{
    "@class": "org.apereo.cas.authentication.principal.SimplePrincipal",
    "id": "koal",
    "attributes": {}
}

可能的相應代碼如下:

Code Result
200 Successful authentication.
403 Produces a AccountDisabledException
404 Produces a AccountNotFoundException
423 Produces a AccountLockedException
412 Produces a AccountExpiredException
428 Produces a AccountPasswordMustChangeException
Other Produces a FailedLoginException

Rest認證示例

  • 編寫認證服務

代碼在倉庫中的user_center下,其中用戶名和密碼是寫死的,可根據需要進行更改

  • 啓動認證服務
  • application.properties中增加
#--------------------------------
#  rest認證
#--------------------------------
#http://10.0.90.30:8000/login是在user_center項目中定義的登錄地址
cas.authn.rest.uri=http://10.0.90.30:8000/login
cas.authn.rest.name=rest-cas
  • 重新打包cas.war,重啓tocmat,進入登錄頁面,在用戶名密碼中輸入koal/123,可以在認證服務的控制檯看到如下日誌:
    在這裏插入圖片描述
    並且CAS頁面也顯示登錄成功。
    在這裏插入圖片描述
    修改下代碼,將賬戶設置爲不可用,重新執行上面步驟,結果如下:
    在這裏插入圖片描述

搭建CAS-MANAGEMENT

  • 克隆倉庫到本地https://github.com/apereo/cas-management-overlay
  • 修改application.properties中的CAS SERVER如下
##
# CAS Server
#
cas.server.name=https://127.0.0.1:8443
cas.server.prefix=${cas.server.name}/cas
  • 執行build.cmd gencert生成證書,將生成的thekeystore文件拷貝到,src/resources下,修改application.properteis文件,支持HTTPS
server.ssl.key-store=classpath:thekeystore
server.ssl.key-store-password=changeit
server.ssl.key-password=changeit
  • 執行mvn clean package打包
  • 啓動前需要將搭建CAS-SERVER是產生的證書(cas.cer)導入到jre
C:\Program Files\Java\jdk1.8.0_161\jre\lib\security>keytool -importcert -file D:\etc\cas\cas.cer -keystore cacerts -storepass changeit
  • 啓動cas-management.war或放入tomcat中啓動
  • 訪問https://127.0.0.1:8444/cas-management,頁面會被重定向到cas-server的登錄頁面,輸入用戶名密碼,登陸成功後會重定向到cas-management的管理頁面

客戶端接入CAS

應用說明

應用名 描述 端口 資源地址
cas-overlay-template CAS SERVER 8443 /cas/login
cas-management-overlay CAS服務管理端 8444 /cas-management
user_center 用戶認證中心,實現了CAS SERVER的認證接口。目前是靜態的只支持koal/123 8000 /login
app 應用1 8880 /index
app2 應用2 8881 /index

相關代碼可在倉庫中查看

  • 啓動cas-overlay-template,啓動方法可參考前面內容
  • 啓動user_center
  • 啓用app
  • 啓動app2
  • 在瀏覽器輸入http://10.0.90.30:8880/index訪問應用1,因爲沒有登錄的原因,被重定向到CAS的登錄頁面
    在這裏插入圖片描述
  • 輸入koal/123,登錄到app1的首頁
    在這裏插入圖片描述
  • 點擊跳轉到應用2,可進入app2的首頁,並且不需要重新登錄
    在這裏插入圖片描述

製作鏡像

目前通過拷貝war包的形式,以java -jar在容器中運行,要求JDK1.8+

# 指定JRE版本,這裏請替換成自己的鏡像
FROM vitruex/builder:gradle-4.10.2-openjdk-7-openjdk-8-docker-18

#作者
MAINTAINER [email protected]
# 拷貝CAS SERVER
COPY cas.war /
# 拷貝站點證書
COPY cas.cer /
# 拷貝CAS MANAGEMENT
COPY jdk-8u231-linux-x64.tar.gz /
RUN tar -zxvf /jdk-8u231-linux-x64.tar.gz

#暴露端口

EXPOSE 8443 8444

ENTRYPOINT (sleep 30 && sh -c '/bin/echo -e "y"| keytool -importcert -file cas.cer -keystore /jdk1.8.0_231/jre/lib/security/cacerts -storepass changeit') & \
            (sleep 20 && /jdk1.8.0_231/bin/java -jar /cas.war &) & \
           tail -f /dev/null

鳴謝

參考許多大神的博客,具體忘記有哪些,這裏統一感謝一下。

示例代碼

由於精力有限,目前只是初步瞭解了CAS單點登錄系統,更深層次的內容後續繼續學習

代碼中將idea的配置也上傳了,如果不需要請刪除。 代碼連接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章