基於CAS的WEB單點登入(sso)服務端及其tomcat/nginx https配置

jwolf2發表於2020-10-27

一、關於SSO單點登入

單點登入sso的實現常見的有Oauth2(當前主流,較複雜)和CAS(Center Authentication Server),它們的區別。這裡先研究一把apereo 實現的CAS SSO。

二、CAS基本原理,參考https://www.jianshu.com/p/b7de8e4cf217

    

 

  1. 訪問服務:SSO 客戶端傳送請求訪問應用系統提供的服務資源。
  2. 定向認證:SSO 客戶端會重定向使用者請求到 SSO 伺服器。
  3. 使用者認證:使用者身份認證。
  4. 發放票據: SSO 伺服器會產生一個隨機的 Service Ticket 。
  5. 驗證票據: SSO 伺服器驗證票據 ST 的合法性,驗證通過後,允許客戶端訪問服務。(每次請求都會到server端驗證ST)
  6. 傳輸使用者資訊: SSO 伺服器驗證票據通過後,傳輸使用者認證結果資訊給客戶端。

CAS Client 與受保護的客戶端應用部署在一起,以 Filter 方式保護 Web 應用的受保護資源,過濾從客戶端過來的每一個 Web 請求,同時, CAS Client 會分析 HTTP 請求中是否包含請求 Service Ticket( ST 上圖中的 Ticket) ,如果沒有,則說明該使用者是沒有經過認證的;於是 CAS Client 會重定向使用者請求到 CAS Server ( Step 2 ),並傳遞 Service (要訪問的目的資源地址)。 Step 3 是使用者認證過程,如果使用者提供了正確的 Credentials , CAS Server 隨機產生一個相當長度、唯一、不可偽造的 Service Ticket ,並快取以待將來驗證,並且重定向使用者到 Service 所在地址(附帶剛才產生的 Service Ticket ) , 併為客戶端瀏覽器設定一個 Ticket Granted Cookie ( TGC ) ; CAS Client 在拿到 Service 和新產生的 Ticket 過後,在 Step 5 和 Step6 中與 CAS Server 進行身份核實,以確保 Service Ticket 的合法性。在該協議中,所有與 CAS Server 的互動均採用 SSL 協議,以確保 ST 和 TGC 的安全性。協議工作過程中會有 2 次重定向 的過程。但是 CAS Client 與 CAS Server 之間進行 Ticket 驗證的過程對於使用者是透明的(使用 HttpsURLConnection )。

應用系統將登入請求轉給認證中心,這個很好解決,我們一個HTTP重定向即可實現。現在的問題是,使用者在認證中心登入後,認證中心如何將訊息轉回給該系統?這是在單web系統中不存在的問題。我們知道HTTP協議傳遞訊息只能通過請求引數方式或cookie方式,cookie跨域問題不能解決,我們只能通過URL請求引數。我們可以將認證通過訊息做成一個令牌(token)再利用HTTP重定向傳遞給應用系統。但現在的關鍵是:該系統如何判斷這個令牌的真偽?如果判斷這個令牌確實是由認證中心發出的,且是有效的?我們還需要應用系統和認證中心之間再來個直接通訊,來驗證這個令牌確實是認證中心發出的,且是有效的。由於應用系統和認證中心是屬於服務端之間的通訊,不經過使用者瀏覽器,相對是安全的。

假如現在應用叢集中又兩個系統A、B。當客戶首次登入A系統的時候,流程如下:

  1. 使用者瀏覽器訪問系統A需登入受限資源。
  2. 系統A發現該請求需要登入,將請求重定向到認證中心,進行登入。
  3. 認證中心呈現登入頁面,使用者登入,登入成功後,認證中心重定向請求到系統A,並附上認證通過令牌。
  4. 系統A與認證中心通訊,驗證令牌有效,證明使用者已登入。
  5. 系統A將受限資源返給使用者。

三、認證服務端部署

因為6.X版本需要JDK11+,故使用較舊的5.3(JDK8+)版本,地址https://github.com/apereo/cas-overlay-template/tree/5.3,clone或下載zip,進入專案根目錄mvm clean package打成一個cas.war包。放到Tomcat webapp並啟動tomcat,瀏覽器訪問http://192.168.154.134:8080/cas/login ,頁面稍微改一下,加上公司logo等就可以了

四、https配置(Tomcat、Nginx)

tomcat直接支援https,參考https://www.cnblogs.com/wanghaoyuhappy/p/5267702.html

#生成證書,密碼123456
keytool -genkeypair -alias "futurecloud" -keyalg "RSA" -keystore "/etc/cas/tomcat.keystore"

tomcat server.xml配置https

<Connector
    protocol="org.apache.coyote.http11.Http11NioProtocol" 
    port="8443" maxThreads="200" 
    scheme="https" secure="true" SSLEnabled="true" 
    keystoreFile="/etc/cas/tomcat.keystore" keystorePass="123456" 
    clientAuth="false" sslProtocol="TLS"/>

企業中一般配置Nginx支援https進行反向代理

檢查Nginx是否已安裝ssl模組

[root@master nginx-1.7.4]# nginx -V
nginx version: nginx/1.7.4
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

如果沒有

#重新配置
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
#重新編譯make,不需要make  install安裝。否則會覆蓋原有的模組

或重新安裝Nginx (docker安裝參考

wget http://nginx.org/download/nginx-1.7.4.tar.gz

tar -zxvf nginx-1.7.4.tar.gz
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-
http_ssl_module

make

make install

nginx -V

nginx -s quit 

nginx -c /usr/XXX/nginx.conf 如重新安裝最好帶配置啟動,避免用錯配置

通過openssl生成證書

1)設定server.key,這裡需要設定兩遍密碼123456:

openssl genrsa -des3 -out server.key 1024

2)不填或隨便填:

openssl req -new -key server.key -out server.csr

3) 寫RSA祕鑰(這裡也要求輸入之前設定的密碼):

openssl rsa -in server.key -out server_nopwd.key

4)生成私鑰:

openssl x509 -req -days 365 -in server.csr -signkey server_nopwd.key -out server.crt

 Nginx使用生成的證書配置cas server端https訪問

server {

    listen    81;       #偵聽80埠,如果強制所有的訪問都必須是HTTPs的,這行需要登出掉
    listen    443 ssl;
    server_name  localhost; #域名
    #ssl on;   ####如果強制HTTPs訪問,這行要開啟
    ssl_certificate /etc/cas/server.crt;
    ssl_certificate_key /etc/cas/server_nopwd.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_protocols  SSLv2 SSLv3 TLSv1.2;    # 指定密碼為openssl支援的格式
    ssl_ciphers  HIGH:!aNULL:!MD5;  # 密碼加密方式
    ssl_prefer_server_ciphers  on;  # 依賴SSLv3和TLSv1協議的伺服器密碼將優先於客戶端密碼

   location / {
            #root   html;
            #index  index.html index.htm;
          proxy_pass http://localhost:8080; #tomcat就沒必要配置https了
        }
}

頁面訪問

 

 

 

相關文章