前言
前端時(shí)間公司讓我研究一下單點(diǎn)登錄,主要目的是如何在現(xiàn)有的框架中引入單點(diǎn)登錄功能。說(shuō)實(shí)話,由于之前沒(méi)有接觸過(guò),而且網(wǎng)上資料質(zhì)量參差不齊,甚至有些誤人子弟,讓我在實(shí)現(xiàn)過(guò)程中踩了不少坑。現(xiàn)在,我將一些學(xué)習(xí)和實(shí)踐的心得通過(guò)本文記錄下來(lái),希望能或多或少幫到大家。
起初,我打算僅用一篇文章完成介紹,但我的目標(biāo)是盡量能淺顯易懂,并且為了能讓大家方便復(fù)現(xiàn),所以最終決定以系列的形式進(jìn)行探討。
概要
單點(diǎn)登錄和CAS
單點(diǎn)登錄(Single Sign On),簡(jiǎn)稱(chēng) SSO,其概念網(wǎng)上一搜便知,我不做廢話。簡(jiǎn)單來(lái)說(shuō),就是只要一次登錄了某個(gè)子系統(tǒng),就順帶登錄了其他的子系統(tǒng)。其目的很簡(jiǎn)單,就是為了減少用戶訪問(wèn)子系統(tǒng)的成本。
目前,實(shí)現(xiàn)單點(diǎn)登錄最流行的是CAS框架,這是一個(gè)由耶魯大學(xué)主導(dǎo)的開(kāi)源框架,github地址為:
https://github.com/apereo/cas
截止本文撰寫(xiě)時(shí),最新穩(wěn)定版本為5.3.2。網(wǎng)上的資料教程大多數(shù)都是基于4.X版本,已經(jīng)嚴(yán)重過(guò)時(shí),2016年后官方也不在更新維護(hù),不再推薦大家使用。
CAS 5.X要求JDK版本最低為1.8。并且基于Spring Boot進(jìn)行了大幅重構(gòu),其使用方式以較4.X大相徑庭,另外,5.X也引入了更多的特性。具體請(qǐng)參見(jiàn)官方文檔。
需要注意的一點(diǎn)是,在4.X時(shí)代,CAS由jasig社區(qū)托管,在5.X時(shí)代,CAS已被apereo社區(qū)托管,因此,大家在maven下載依賴(lài)時(shí),要注意區(qū)分,如:
- apereo
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
- jasig
<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-core</artifactId>
<version>4.2.7</version>
</dependency>
CAS原理
CAS的原理稍稍有些復(fù)雜,我們至少要了解TGT、TGC、ST這個(gè)三個(gè)核心概念,以及整個(gè)單點(diǎn)登錄的實(shí)現(xiàn)過(guò)程。強(qiáng)烈推薦博文《前端需要了解的 SSO 與 CAS 知識(shí)》,建議大家務(wù)必提前細(xì)細(xì)品味,鉆研透徹,否則后續(xù)的實(shí)現(xiàn)過(guò)程會(huì)讓你覺(jué)得云里霧里。
了解了CAS的原理后,還需要注意一點(diǎn),CAS默認(rèn)是基于瀏覽器的單點(diǎn)登錄方式,其依賴(lài)于瀏覽器的cookie和重定向機(jī)制。但是,由于移動(dòng)互聯(lián)網(wǎng)的發(fā)展,客戶端的接入方式已經(jīng)不限于瀏覽器,我們更多的需要支持原生應(yīng)用(如安卓、IOS)的接入。因此,CAS的基于cookie和重定向機(jī)制的瀏覽器登錄認(rèn)證方式有了很大的局限性。另外,當(dāng)下前后端分離的開(kāi)發(fā)形式已非常廣泛,前后端之間都通過(guò)REST接口進(jìn)行請(qǐng)求。
基于上面的因素,CAS又單獨(dú)提供了REST的擴(kuò)展。本系列對(duì)兩種方式(瀏覽器方式、REST方式)的實(shí)現(xiàn)都會(huì)進(jìn)行介紹。
實(shí)現(xiàn)服務(wù)端
CAS是由客戶端和服務(wù)端兩部分構(gòu)成的,本文將先介紹服務(wù)端的實(shí)現(xiàn)過(guò)程,IDE使用Idea 2018,JDK使用1.8,Gradle使用4.4。
服務(wù)端實(shí)際上是一個(gè)Web工程,需要放在Web容器如Tomcat中運(yùn)行。CAS官方推薦采用overlay方式來(lái)實(shí)現(xiàn)服務(wù)端,詳見(jiàn)官方文檔。
何為overlay,中文意為覆蓋。一言以蔽之,overlay就是官方提供給你一個(gè)模板工程,我們只需要將修改或定制的文件覆蓋模板工程中對(duì)應(yīng)位置的對(duì)應(yīng)文件(包括代碼和資源文件)即可。
為何需要overlay,官方解釋很清楚:
- There is no need to download/build from the source.
- Upgrades are tremendously easier in most cases by simply adjusting the build script to download the newer CAS release.
- Rather than hosting the entire software source code, as the deployer you ONLY keep your own local customizations which makes change tracking much easier.
- Tracking changes inside a source control repository is very lightweight, again simply because only relevant changes (and not the entire software) is managed.
以上,我認(rèn)為最關(guān)鍵有兩點(diǎn):
- 如果直接修改源碼,CAS特性升級(jí)后源碼有變動(dòng),我們還得重新適配我們的修改
- 使用overlay,由于不直接修改源碼,我們可以方便的追蹤自己定制的功能,可以清楚的知道我們修改了哪些
1.下載cas-overlay-template工程
首先,下載cas-overlay-template工程。CAS同時(shí)提供了maven和gradle兩個(gè)類(lèi)型,大同小異,本文將基于gradle進(jìn)行介紹,請(qǐng)戳下載地址。
使用Idea打開(kāi)工程,等待依賴(lài)下載后,工程如下:

該工程的gradle構(gòu)建文件稍許復(fù)雜,有些功能或許暫時(shí)用不上。并且,如果在一個(gè)已有的老舊系統(tǒng)中引入CAS,直接用cas-overlay-template工程當(dāng)然不合適,勢(shì)必需要進(jìn)行修改。所以,本文將抽取其關(guān)鍵核心的配置,取其精華,重新創(chuàng)建新的工程做以示范。
另外,根據(jù)官方介紹,該工程支持兩種運(yùn)行方式:
- 通過(guò)
java -jar *.war啟動(dòng) - 通過(guò)部署至Web容器(如tomcat)啟動(dòng)
對(duì)于方式1,實(shí)際上是因?yàn)?code>cas-overlay-template這個(gè)Spring Boot工程內(nèi)嵌了tomcat容器,總所周知,這也是Spring Boot推薦的運(yùn)行方式。方式2實(shí)際上是最常見(jiàn)的、標(biāo)準(zhǔn)的Java Web工程的運(yùn)行方式。這里,由于方式1相對(duì)較簡(jiǎn)單,本文將基于方式2進(jìn)行介紹。
2.搭建服務(wù)端工程
我們重點(diǎn)關(guān)注cas-overlay-template工程中cas模塊的build.gradle文件,稍許復(fù)雜,我們只聚焦其依賴(lài):
dependencies {
compile "org.apereo.cas:cas-server-webapp-tomcat:${project.'cas.version'}@war"
if (!project.hasProperty('bootiful')) {
// Other dependencies may be listed here...
} else {
println "Running CAS in Bootiful mode; all dependencies except the CAS web application are ignored."
}
}
結(jié)合gradle.properteis,可以發(fā)現(xiàn)該工程只依賴(lài)于:
org.apereo.cas:cas-server-webapp-tomcat:5.3.2@war
在菜單Build/Build Artifacts中進(jìn)行構(gòu)建,選擇exploded:


執(zhí)行后,在build目錄中可以看到war文件:

我們將基于這個(gè)war文件搭建自己的服務(wù)端。新建gradle工程,結(jié)構(gòu)如下:

build.gradle由cas-overlay-template進(jìn)行精簡(jiǎn),如下:
group 'com.mystudy.cas'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: "org.springframework.boot"
apply plugin: "war"
sourceCompatibility = 1.8
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:1.5.14.RELEASE"
}
}
springBoot {
mainClass = "org.springframework.boot.loader.WarLauncher"
}
bootRepackage {
mainClass = "org.apereo.cas.web.CasWebApplication"
executable = false
excludeDevtools = false
}
bootRun {
addResources = true
classpath = sourceSets.main.compileClasspath
}
war {
baseName 'cas'
entryCompression = ZipEntryCompression.STORED
}
repositories {
mavenCentral()
}
dependencies {
compile "org.apereo.cas:cas-server-webapp-tomcat:5.3.2@war"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
在src\main下新建包webapp,然后解壓上一小節(jié)獲取的war包,將META-INF、org、WEB-INF目錄拷貝至webapp內(nèi):

如上,可以看到這是一個(gè)標(biāo)準(zhǔn)的Web工程。CAS默認(rèn)設(shè)計(jì)了基本的Web頁(yè)面(基于angular和thymeleaf),在此基礎(chǔ)上我們可以按需定制。
另外,WEB-INF\lib目錄中的依賴(lài)文件較多,有334個(gè)。很明顯,使用overlay方式,我們不得不將這些依賴(lài)維護(hù)到代碼倉(cāng)庫(kù)中,這是因?yàn)楣俜讲](méi)有提供這些文件的直接依賴(lài)(只能通過(guò)war解壓獲?。.?dāng)然,不得已的話你也可以直接使用源碼進(jìn)行開(kāi)發(fā)不使用overlay方式。
根據(jù)overlay的思路,我們只需要在源碼路徑src\main中進(jìn)行定制,并將所有自定義配置文件都放置在src\main\resources中,但若要修改CAS的配置,一定要保證配置文件的路徑和名稱(chēng)與webapp\WEB-INF中一致。
比如,我們要修改WEB-INF\application.properties這個(gè)Spring Boot配置文件中的server.port,我們只需要拷貝其至src\main\resources目錄下進(jìn)行修改,并且備份WEB-INF中的application.properties為其他名稱(chēng)(如application2.properties)即可。這樣,構(gòu)建后的War包中的WEB-INF就會(huì)替換為自己的配置文件。
這里提一個(gè)小常識(shí),
src\main中的所有源碼和資源文件在構(gòu)建后,都會(huì)依照包路徑保存到WEB-INF\classes目錄下,而外部的依賴(lài)會(huì)全部保存到WEB-INF\lib目錄下。
3.服務(wù)端運(yùn)行
至此,我們已經(jīng)搭建起一個(gè)最基本的Hello World,現(xiàn)在使用Idea配合Tomcat進(jìn)行啟動(dòng)。先配置Tomcat,修改Deployment,添加部署構(gòu)建:

Server保持如下設(shè)置即可:

在Idea中啟動(dòng)Tomcat,耐心等上片刻,期間將會(huì)看到如下藍(lán)色提示信息:

啟動(dòng)成功后,開(kāi)始監(jiān)聽(tīng)請(qǐng)求,提示“READY":

并且,Idea會(huì)自動(dòng)打開(kāi)瀏覽器去訪問(wèn)CAS自帶的登錄界面:

賬號(hào)密碼在哪里?請(qǐng)看application.properties最后:
##
# CAS Authentication Credentials
#
cas.authn.accept.users=casuser::Mellon
如上,用戶名為casuser,密碼為Mellon,登錄成功后提示:

當(dāng)然,我們可以在application.properties中修改用戶名和密碼(別忘了拷貝application.properties)。
廢話
到目前為止,我們搭建了一個(gè)簡(jiǎn)單的CAS服務(wù)端,下一章節(jié)《如何使用CAS 5 實(shí)現(xiàn)單點(diǎn)登錄(二、搭建客戶端)》敬請(qǐng)期待。
本人水平有限,難免有錯(cuò)誤或遺漏之處,望大家指正和諒解,歡迎評(píng)論留言。