Apereo CAS 爬坑

心血來潮想給公司搭個單點(diǎn)登錄系統(tǒng)魏烫,畢竟內(nèi)網(wǎng)這么多系統(tǒng)怖亭,每個系統(tǒng)都一套賬號密碼,這樣好low挚瘟。CAS提供了一個統(tǒng)一認(rèn)證服務(wù)叹谁,所有系統(tǒng)直接向CAS去請求登陸認(rèn)證,而用戶只在CAS登陸一次就夠了乘盖,在大一點(diǎn)的公司里基本都有這種服務(wù)焰檩,叫SSO(Single sign-on)。
找了找開源的SSO订框,看到了CAS析苫,感覺挺屌的,一直在更新穿扳,就他了衩侥。然后就開始爬坑了,記錄一下矛物,免得日后忘了又爬一次茫死。

CAS-Overlay-Template

這個項(xiàng)目很大,還需要很多自定義配置履羞,所以不可能做成開箱即用峦萎。CAS-Overlay-Template 就是一個模板項(xiàng)目,clone下來忆首, 修改配置爱榔,然后是直接跑還是打包war或者打包docker都好說。
新版本的 CAS-Overlay-Template 已經(jīng)改為Gradle編譯糙及,我喜歡Gradle详幽。
clone下來后,直接 先運(yùn)行
./build.sh copy
再運(yùn)行
./build.sh run
就跑起來了。

編譯配置

跑起來個屁铐维。
默認(rèn)是CAS 6.0版本着帽,直接用Java11了,要跑6.0版本先去裝個jdk11雳灾,配好環(huán)境。我踩坑的時候6.0還是RC版本冯凹,發(fā)現(xiàn)有bug就還是滾回5.3.5谎亩,配置這些東西在gradle.properties

# Versions
cas.version=5.3.5  // 可以改成6.0.0-rc3
springBootVersion=2.1.0.RELEASE

appServer=-tomcat

gradleVersion=4.10.2
tomcatVersion=9
tomcatFullVersion=9.0.12

group=你的組織名
sourceCompatibility=8   // 6.0以上就改成11
targetCompatibility=8    // 6.0以上就改成11

# Location of the downloaded CAS shell JAR
shellDir=build/libs

# use without "-slim" in tag name if you want tools like jstack, adds about 100MB to image size
baseDockerImage=openjdk:8-slim   // 6.0以上就改成11

同時,還有增加幾個依賴宇姚,因?yàn)镃AS完全是插件化設(shè)計

    compile "org.apereo.cas:cas-server-support-jdbc:${casServerVersion}"
    compile "org.apereo.cas:cas-server-support-jdbc-drivers:${casServerVersion}"
    compile "org.apereo.cas:cas-server-support-pm:${casServerVersion}"
    compile "org.apereo.cas:cas-server-support-pm-jdbc:${casServerVersion}"

然后下1個小時依賴就可以跑起來了匈庭,可喜可賀,可喜可賀浑劳。

配置目錄

image.png

這個目錄阱持,里面包含了所有的配置,基本上改這里面的東西就夠了魔熏。

這個配置目錄是如何生效的衷咽?

之所以先運(yùn)行 ./build.sh copy 是因?yàn)?/p>

function copy() {
    echo -e "Creating configuration directory under /etc/cas"
    mkdir -p /etc/cas/config

    echo -e "Copying configuration files from etc/cas to /etc/cas"
    cp -rfv ./etc/cas/* /etc/cas
}

他會把配置文件復(fù)制進(jìn)系統(tǒng)配置目錄鸽扁,然后 Springboot 啟動后會去讀這個系統(tǒng)配置目錄。
另外镶骗,注意一下 src/main/jib/docker/entrypoint.sh 里面是類似 Dockerfile

#!/bin/sh

#echo -e "\nChecking java..."
#java -version

#echo -e "\nCreating CAS configuration directories..."
mkdir -p /etc/cas/config
mkdir -p /etc/cas/services

#echo "Listing provided CAS docker artifacts..."
#ls -R docker/cas

#echo -e "\nMoving CAS configuration artifacts..."
mv docker/cas/thekeystore /etc/cas 2>/dev/null
mv docker/cas/config/*.* /etc/cas/config 2>/dev/null
mv docker/cas/services/*.* /etc/cas/services 2>/dev/null

#echo -e "\nListing CAS configuration under /etc/cas..."
#ls -R /etc/cas

echo -e "\nRunning CAS..."
exec java -Xms512m -Xmx2048M -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -jar docker/cas/war/sso.war

打包鏡像時桶现,也會直接把配置目錄復(fù)制進(jìn)鏡像的系統(tǒng)配置目錄

build.sh

常用操作 build.sh 都已經(jīng)寫好了,常用的比如

  • ./build.sh copy 復(fù)制配置到系統(tǒng)目錄
  • ./build.sh run 運(yùn)行CAS
  • ./build.sh docker 打包鏡像
  • ./build.sh debug Debug CAS

配置

然后幾乎所有的服務(wù)配置都在 cas/config/cas.properties
一點(diǎn)一點(diǎn)的補(bǔ)充吧鼎姊,把example.com換成自己的域名骡和。
下面是 5.3.5的配置,5.2.x 的配置不一樣相寇,6.0.0也不一樣慰于,文檔沒寫,我也不寫??唤衫。
后文會介紹怎么去源碼看當(dāng)前版本的配置項(xiàng)

服務(wù)地址

cas.server.name=http://sso.example.com
cas.server.prefix=${cas.server.name}    //要使用根Path訪問婆赠,比如 http://sso.example.com 就這樣。默認(rèn)值是`${cas.server.name}/cas`
server.context-path=      //對战授,就是空页藻,這樣就可以使用根Path訪問了,默認(rèn)值是 /cas
server.port=443    // HTTPS的端口,默認(rèn)8443
cas.server.http.enabled=true    // 開啟HTTP植兰,默認(rèn)只有HTTPS份帐,而且我只知道怎么開HTTP,不知道怎么關(guān)HTTPS
cas.server.http.port=80  // 設(shè)置HTTP端口楣导,默認(rèn)8080

上面這幾個配置挺操蛋的废境,我以為 cas.server.prefix 改了就可以 http://sso.example.com 直接訪問了,結(jié)果還是要加上/cas才能訪問筒繁,這個配置是假的噩凹,只是用于各種重定向url填充用。server.context-path 才是真正的 Path毡咏。

數(shù)據(jù)庫認(rèn)證

cas.authn.accept.users=        // 留空才會禁用 Static Authentication
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
cas.authn.jdbc.query[0].url=jdbc:mysql://xxxxxxxxxxxxxxxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.jdbc.query[0].user=xxxxxxx
cas.authn.jdbc.query[0].password=xxxxxxxxx
cas.authn.jdbc.query[0].sql=select * from user where name=?

// 這些配置懶得講了驮宴,網(wǎng)上大部分文章講的都沒問題
cas.authn.jdbc.query[0].fieldPassword=password    
cas.authn.jdbc.query[0].fieldExpired=expired
cas.authn.jdbc.query[0].fieldDisabled=disabled
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

配置數(shù)據(jù)庫認(rèn)證很簡單。去給數(shù)據(jù)庫建個表呕缭。填一下字段名和Sql堵泽,就可以了。然后跑一下試試吧

密碼管理-郵件

CAS支持密碼管理功能恢总,直接網(wǎng)頁上點(diǎn)忘記密碼迎罗,就給你郵箱發(fā)重置郵件,配置比較多片仿,坑也很多

# 發(fā)送郵件纹安,我用的騰訊企業(yè)郵
spring.mail.host=smtp.exmail.qq.com
spring.mail.port=465
spring.mail.username=xxxxxx@example.com
spring.mail.password=xxxxxxx

# 這是騰訊企業(yè)郵的配置,其他郵箱自己配,可能有些坑厢岂,但這個不管CAS的事
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.socketFactory.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.fallback=false
spring.mail.properties.mail.smtp.ssl=true

密碼管理-數(shù)據(jù)庫

改改自己的SQL就好了

cas.authn.pm.enabled=true    // 開啟修改密碼功能
cas.authn.pm.autoLogin=true  // 修改密碼后自動登錄
cas.authn.pm.jdbc.autocommit=true  // 加就是了
cas.authn.pm.jdbc.sqlFindEmail=SELECT email FROM user WHERE name=?
cas.authn.pm.jdbc.sqlChangePassword=UPDATE user SET password=? WHERE name=?
cas.authn.pm.jdbc.url=${cas.authn.jdbc.query[0].url}
cas.authn.pm.jdbc.user=${cas.authn.jdbc.query[0].user}
cas.authn.pm.jdbc.password=${cas.authn.jdbc.query[0].password}
cas.authn.pm.jdbc.dialect=${cas.authn.jdbc.query[0].dialect}
cas.authn.pm.jdbc.driverClass=${cas.authn.jdbc.query[0].driverClass}
# 密碼修改加密規(guī)則光督,這個必須要和原始密碼加密規(guī)則一致
cas.authn.pm.jdbc.passwordEncoder.type=${cas.authn.jdbc.query[0].passwordEncoder.type}
cas.authn.pm.jdbc.passwordEncoder.characterEncoding=${cas.authn.jdbc.query[0].passwordEncoder.characterEncoding}
cas.authn.pm.jdbc.passwordEncoder.encodingAlgorithm=${cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm}
cas.authn.pm.jdbc.passwordEncoder.secret=${cas.authn.jdbc.query[0].passwordEncoder.secret}

密碼管理-業(yè)務(wù)配置

cas.authn.pm.reset.mail.from=${spring.mail.username}
cas.authn.pm.reset.mail.subject=[XXX公司 SSO系統(tǒng)] 重置密碼
# 郵件內(nèi)容,必須要有%s咪笑,因?yàn)闀梢粋€連接并且?guī)Я藅oken可帽,否則無法打開鏈接,當(dāng)然這個鏈接也和cas.server.prefix有關(guān)系
cas.authn.pm.reset.mail.text=[季諾科技 SSO]打開以下鏈接重置您的密碼窗怒,10分鐘后失效: %s
cas.authn.pm.reset.expirationMinutes=10  // 郵件有效期
cas.authn.pm.reset.securityQuestionsEnabled=false    // 問題驗(yàn)證,我覺得這個操作很蠢蓄拣,就關(guān)了
# 8-32位扬虚,必須包含大小寫字母,數(shù)字球恤,字符辜昵。你可以填其他密碼檢驗(yàn)正則
cas.authn.pm.policyPattern=^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,32}

神坑

路由轉(zhuǎn)發(fā)環(huán)境下的IP校驗(yàn)

到這里可能本地跑起來沒問題了,修改密碼都正常咽斧。一部署到線上就不能修改密碼堪置,從郵箱驗(yàn)證鏈接點(diǎn)過去,CAS每次都拒絕此次密碼修改請求张惹。為啥舀锨?
翻了大片的源碼,終于找到了原因宛逗。郵箱里收到的鏈接參數(shù)是加了密的坎匿,取消加密的話就很容易看出問題。

http://sso.example.com/login?pswdrst={"jti":"ad06632d-dcee-43e0-bf0f-639150912b96","iss":"http://sso.example.com","aud":"http://sso.example.com","exp":1542541827,"iat":1542541227,"origin":"17*.17*.0.11","client":"1*.1*.97.138","sub":"jude"}

token里包含了請求郵件驗(yàn)證時的客戶端IP雷激,也不知道為啥替蔬,Nginx轉(zhuǎn)發(fā)后,他拿到的IP就老是不對屎暇,點(diǎn)擊鏈接訪問時承桥,IP對不上他就不認(rèn)這次請求。
普通的直接部署的CAS系統(tǒng)根悼,不加這個沒問題凶异。但我們的內(nèi)網(wǎng)環(huán)境是有一臺Nginx路由,所有請求都會經(jīng)過他轉(zhuǎn)發(fā)番挺,就出問題唠帝。
差點(diǎn)去改源碼了,好在無聊翻源碼時找到玄柏,CAS原來留了一手來處理這個問題襟衰。

cas.audit.alternateClientAddrHeaderName=X-Forwarded-For

添加這個配置, CAS就會從Header里讀X-Forwarded-For來確認(rèn)客戶端IP粪摘,這樣就不存在轉(zhuǎn)發(fā)后IP不對的問題了瀑晒。

6.0版本的密碼修改BUG

我也不清楚6.0版本加了找回用戶名這個積累功能后绍坝,為啥找回密碼頁面他老是發(fā)請求到找回用戶名的接口上去。導(dǎo)致找回密碼和找回用戶名2個功能都不能正常工作苔悦。源碼好多轩褐,對JSP無力,沒細(xì)查玖详,改回5.3.5把介,BUG消失,放棄6.0蟋座。

找配置文檔

我上面的配置有很多拗踢,官網(wǎng)文檔寫的很糟,又少又老還跳來跳去向臀,還每個版本都要改配置項(xiàng)(5.2.x, 5.3.x, 6.0.x都很多不一樣)巢墅。
網(wǎng)上大部分文檔都是5.2版本的祖?zhèn)髋渲茫婚_始真是惡心死我了券膀。
還是得自己去翻源碼君纫,先找到 CasServerProperties 這個類,他在

image.png

這個類就是配置的映射芹彬,還有少數(shù)注釋講了很多官方文檔沒說的操作蓄髓。
image.png

照著這個類來填配置就行了。

棄坑

好不容易終于跑起來這個坑B玩意了雀监,但十分不建議使用CAS双吆,CAS優(yōu)勢是開放,適合二次開發(fā)会前。
但十分難用......去用keycloak吧好乐。配置簡單,界面還好看瓦宜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔚万,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子临庇,更是在濱河造成了極大的恐慌反璃,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件假夺,死亡現(xiàn)場離奇詭異淮蜈,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)已卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門梧田,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事裁眯○睦妫” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵穿稳,是天一觀的道長存皂。 經(jīng)常有香客問我,道長逢艘,這世上最難降的妖魔是什么旦袋? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮它改,結(jié)果婚禮上猜憎,老公的妹妹穿的比我還像新娘。我一直安慰自己搔课,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布截亦。 她就那樣靜靜地躺著爬泥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪崩瓤。 梳的紋絲不亂的頭發(fā)上袍啡,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音却桶,去河邊找鬼境输。 笑死,一個胖子當(dāng)著我的面吹牛颖系,可吹牛的內(nèi)容都是我干的嗅剖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嘁扼,長吁一口氣:“原來是場噩夢啊……” “哼信粮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起趁啸,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤强缘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后不傅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旅掂,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年访娶,在試婚紗的時候發(fā)現(xiàn)自己被綠了商虐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖称龙,靈堂內(nèi)的尸體忽然破棺而出留拾,到底是詐尸還是另有隱情,我是刑警寧澤鲫尊,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布痴柔,位于F島的核電站,受9級特大地震影響疫向,放射性物質(zhì)發(fā)生泄漏咳蔚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一搔驼、第九天 我趴在偏房一處隱蔽的房頂上張望谈火。 院中可真熱鬧,春花似錦舌涨、人聲如沸糯耍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽温技。三九已至,卻和暖如春扭粱,著一層夾襖步出監(jiān)牢的瞬間舵鳞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工琢蛤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜓堕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓博其,卻偏偏與公主長得像套才,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贺奠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355