CAS5.3伺服器搭建與客戶端整合SpringBoot以及踩坑筆記
匯出證書(1和2步驟是找了課程,隨便寫了一下存記錄,不過對於自己測試不投入使用應該不影響)
C:\Users\Ddlm2>keytool -genkey -alias testcas -keystore D:/testcas -storepass 123456 -keyalg RSA -validity 3650
您的名字與姓氏是什麼?
[Unknown]: test
您的組織單位名稱是什麼?
[Unknown]: test
您的組織名稱是什麼?
[Unknown]: test
您所在的城市或區域名稱是什麼?
[Unknown]: test
您所在的省/市/自治區名稱是什麼?
[Unknown]: test
該單位的雙字母國家/地區程式碼是什麼?
[Unknown]: test
CN=test, OU=test, O=test, L=test, ST=test, C=test是否正確?
[否]: Y 輸入 <testcas> 的金鑰口令
(如果和金鑰庫口令相同, 按回車):
再次輸入新口令: Warning:
JKS 金鑰庫使用專用格式。建議使用 "keytool -importkeystore -srckeystore D:/testcas -destkeystore D:/testcas -deststoretype pkcs12" 遷 移到行業標準格式 PKCS12。 C:\Users\Ddlm2>keytool -genkey -alias testcas -keystore D:/testcas -storepass 123456 -keyalg RSA -validity 3650 -export -trustcacerts -file D:/testcas.cer
儲存在檔案 <D:/testcas.cer> 中的證書 Warning:
JKS 金鑰庫使用專用格式。建議使用 "keytool -importkeystore -srckeystore D:/testcas -destkeystore D:/testcas -deststoretype pkcs12" 遷 移到行業標準格式 PKCS12。
匯入jdk的證書庫
C:\Users\Ddlm2>keytool -import -trustcacerts -alias testcas -file D:/testcas.cer
輸入金鑰庫口令:
再次輸入新口令:
所有者: CN=test, OU=test, O=test, L=test, ST=test, C=test
釋出者: CN=test, OU=test, O=test, L=test, ST=test, C=test
序列號: 429f9b95
生效時間: Fri Aug 13 11:15:22 CST 2021, 失效時間: Mon Aug 11 11:15:22 CST 2031
證書指紋:
SHA1: 3A:20:B4:25:12:96:6E:EB:F7:15:15:BE:11:A7:C5:66:60:25:D6:A8
SHA256: 06:80:FC:34:63:27:20:ED:6E:74:CB:51:2B:5B:86:E0:70:C2:CD:65:36:46:52:13:25:0A:B4:9B:7F:67:31:B7
簽名演算法名稱: SHA256withRSA
主體公共金鑰演算法: 2048 位 RSA 金鑰
版本: 3 擴充套件: #1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 24 05 3F B0 42 A4 02 84 70 D1 F2 09 4A AB D8 93 $.?.B...p...J...
0010: 8B 29 85 BB .)..
]
] 是否信任此證書? [否]: y
證書已新增到金鑰庫中
注:應該是在
webapps\cas\WEB-INF\classes
中的application.properties中配置(開頭7行左右)不過自己測試,只會提示密碼洩露不安全什麼的,無大礙。
下載 cas server 安裝包,這裡使用的是5.3。下面的連結都可以使用
https://github.com/apereo/cas-overlay-template/tree/5.3
----------------------------------------
https://wwa.lanzoui.com/b010pvygd
密碼:casserver
打war包。 安裝maven的環境變數(或者匯入idea打包),在cas-overlay-template-5.3目錄開啟cmd命令列使用
mvn package
進行打包,會在target目錄下出現cas.war
檔案,部署tomcat。 將本地tomcat伺服器拷貝出來一份,作為cas伺服器,將war包複製到webapps下面。執行tomcat,war包會自動解壓到car資料夾中。
注:如果cas使用5以上,tomcat必須8以上。
埠對映。 在tomcat目錄下的conf目錄下的server.xml中新增
<Connector port="8332" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- 意為將8332介面轉到8443介面 -->
<!-- 8332是對外的,那麼8443呢,cas預設埠就是8443,applicaion.properties中的第5行左右 -->
注:主要為了防止埠號衝突,都可以任意修改。
新增http協議。 webapps\cas\WEB-INF\classes\services下的HTTPSandIMAPS-10000001.json的第三行修改成
"serviceId" : "^(https|http|imaps)://.*",
使其接受http協議。也可以自定義使用者名稱。 webapps\cas\WEB-INF\classes下的application.properties 最後那裡
cas.authn.accept.users=casuser::Mellon
是預設的使用者名稱和密碼,可以修改為自己喜歡的。
重啟tomcat, 訪問
localhost:8332/cas/login
輸入7步驟中的賬號密碼進行測試。
接下來整理,springboot整合cas client。cas伺服器端返回資料在下面。
新建maven或者springboot專案都可以,開啟pom檔案新增依賴。
<dependencies> <!-- cas的客戶端 -->
<dependency>
<groupId>net.unicon.cas</groupId>
<artifactId>cas-client-autoconfig-support</artifactId>
<version>2.2.0-GA</version>
<exclusions>
<exclusion>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
</exclusion>
</exclusions>
</dependency> <!-- 使用更高版本的cas-client-core -->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.5.0</version>
</dependency> <!-- 故意降的版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency> </dependencies>
注:若啟動時候報錯,且去掉cas相關東西又可以正常啟動。可以嘗試降一下你自己的springboot版本。
新增啟動類,切記
@EnableCasClient
import net.unicon.cas.client.configuration.EnableCasClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* @author ddlm
* @date 2021/08/17 10:53
*/
@EnableCasClient
@SpringBootApplication
public class CASClientOne {
public static void main(String[] args) {
SpringApplication.run(CASClientOne.class, args);
}
}
新增配置,這裡使用的yml,properties就是:變.和=而已。
server:
port: 9101 cas:
# cas伺服器端的地址和埠,注意埠號。
server-url-prefix: http://localhost:8332/cas
server-login-url: http://localhost:8332/cas/login
# 本地的地址,用於回調回來
client-host-url: http://localhost:9101
# 需要攔截的地址(所有為"/*"),可配置陣列
authentication-url-patterns:
- "/auth/login"
- "/auth/createOrder"
validation-type: CAS3
注:攔截的介面是個例子。因為使用場景場景不同:全由cas控制或者只需要登入在自己專案控制。
如果服務端不需要關,只需要使用cas實現單點登入,且獲取資料,如果從session中獲取,需要配置中開啟一下:
cas: use-session: true
,對應獲取資料就request.getSession().getAttribute("key");
隨便寫個介面測試。
@RestController
public class TestController { @RequestMapping("/testFirst")
public String TestMethod() {
return "This is First Method.";
}
}
注:確保url在配置中的攔截範圍內。
為了方便對比,再新建一個專案,步驟一致,起碼介面名、埠名和返回內容修改一下。
啟動兩個專案,訪問第一個專案中的介面,需要登入,登入後。
訪問第二個專案的介面,此時不需要登入即為成功。
擴充套件: 一些部落格中,結合了攔截器進行匹配,這個看需要進行新增,主要是可以忽略介面,加幾層一般都可以避免,如果使用過濾器注意與配置的交集。
@Configuration
public class CASConfig { @Value("${cas.server-url-prefix}")
private String serverUrlPrefix;
@Value("${cas.server-login-url}")
private String serverLoginUrl;
@Value("${cas.client-host-url}")
private String clientHostUrl;
@Value("${ignore-host-url}")
private String ignoreHostUrl; /**
* 授權過濾器
*/
@Bean
public FilterRegistrationBean filterAuthenticationRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new AuthenticationFilter());
// 設定匹配的路徑
registration.addUrlPatterns("/*");
Map<String,String> initParameters = new HashMap<>();
initParameters.put("casServerLoginUrl", serverUrlPrefix);
initParameters.put("serverName", clientHostUrl);
//忽略的url,"|"分隔多個url
initParameters.put("ignorePattern", ignoreHostUrl);
registration.setInitParameters(initParameters);
// 設定載入的順序
registration.setOrder(1);
return registration;
}
}
其中
ignore-host-url
需要另外在yml中配置。
接下來配置cas伺服器從資料庫中獲取使用者名稱和密碼,並返回該人員所有資訊(只是測試使用)。
獲取登入名。為什麼多返回更多內容呢,因為使用者名稱預設會返回,這裡介紹獲取使用者名稱的三種方法。
request.getRemoteUser(); ((Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION)).getPrincipal().getName(); 第二步不getName(),getAttributes();在得到的集合中去get("username"),大概,可以打印出來找一下。
注:從request中能get到的都get過來了,然後轉成json輸出找到的...
CAS伺服器配置連線資料庫。
我測試時候是重新打包的,也可以參考這位大佬的部落格tomcat8搭建cas伺服器,使用MYSQL資料庫
或者這位大佬的:cas5.3.1 從搭建到連線mysql(簡而優美),是直接複製jar包進來,不需要重新打包的。
新增需要訪問資料庫的依賴,在
cas-overlay-template-5.3/pom.xml
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc-drivers</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- 與資料庫版本一致 -->
<version>8.0.23</version>
</dependency>
注:切記最後面那個版本號一定一定一定要跟自己mysql的版本一致。可百度檢視如何檢視MySQL版本。
小版本號也要保證一致!!!
打包,部署,重新按照伺服器的部署修改一下。
修改 webapps\cas\WEB-INF\classes下的application.properties最後部分,註釋掉預設或者自定義的賬號密碼:
# cas.authn.accept.users=casuser::Mellon
新增:
cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/cas_server_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
cas.authn.jdbc.query[0].principalAttributeList=id,username,password,stunumber,stuclass
cas.authn.jdbc.query[0].user=root
cas.authn.jdbc.query[0].password=123456
cas.authn.jdbc.query[0].sql=select id,username,password,stu_number as stuNumber,stu_class as stuClass from student where username=?
cas.authn.jdbc.query[0].fieldPassword=password
# cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver # 忽略https安全協議,使用 HTTP 協議
cas.tgc.secure=false
# 是否開啟json識別功能,預設為false
cas.serviceRegistry.initFromJson=true
# 指明路徑
cas.serviceRegistry.json.location=classpath:/services
注:
- principalAttributeList中是返回的欄位名,如果想要定義別名,需要在sql中使用as重新命名。
- 注意mysql版本號與driverClass的對應。
- 未涉及密碼加密。
- 當不需要定義別名時候,sql可以直接select *
- 見網上說資料庫欄位名帶下劃線返回不回來,經過測試可以返回,如果失敗定義別名可解決。
修改webapps\cas\WEB-INF\classes\services\HTTPSandIMAPS-10000001.json,最後新增:
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|http|imaps)://.*",
"name" : "HTTPS and IMAPS",
"id" : 10000001,
"description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
"evaluationOrder" : 10000,
"attributeReleasePolicy" : {
"@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
}
}
新增attributeReleasePolicy,注意json格式,上面要新增
,
準備MySQL資料庫資料
/*
Navicat Premium Data Transfer Source Server : localMysql
Source Server Type : MySQL
Source Server Version : 80023
Source Host : localhost:3306
Source Schema : cas_server_demo Target Server Type : MySQL
Target Server Version : 80023
File Encoding : 65001 Date: 17/08/2021 13:56:44
*/ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`stu_number` int(0) NULL DEFAULT NULL,
`stu_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, 'admin', 'admin', 222222424, '234');
INSERT INTO `student` VALUES (2, 'test1', 'test1', 123454321, '235'); SET FOREIGN_KEY_CHECKS = 1;
重啟tomcat,注意啟動日誌。
springboot cas client取資料,我整理了一個簡易工具類。
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion; import javax.servlet.http.HttpServletRequest;
import java.util.Map; public class CASUtil {
private static HttpServletRequest request; /**
* 從cas中獲取使用者名稱
*
* @param request Http請求
* @return 登入cas伺服器的使用者名稱
*/
public static String getAccountNameFromCas(HttpServletRequest request) {
CASUtil.request = request;
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
if (assertion != null) {
AttributePrincipal principal = assertion.getPrincipal();
return principal == null ? null : principal.getName();
} else {
return null;
}
} /**
* 從cas返回值中獲取內容
*
* @param request Http 請求
* @param attr 需要獲取值的鍵名
* @return 鍵名attr對應的值
*/
public static String getAttributeFromCas(HttpServletRequest request, String attr) {
CASUtil.request = request;
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); if (assertion != null) {
AttributePrincipal principal = assertion.getPrincipal();
// 一般不會為空,因為有attributes
if(principal != null) {
Object obj = principal.getAttributes().get(attr);
return obj == null ? null : obj.toString();
}
}
return null;
}
}
至此,完畢。
整理要點
- cas伺服器
- 埠(server.xml)
- 連線資料庫(application.properties)
- 修改json配置檔案(HTTPSandIMAPS-10000001.json)
- 連線資料庫依賴的驅動版本號
- cas與tomcat版本
- cas客戶端
- 依賴版本號(cas和springboot的)
@EnableCasClient
註解- 配置檔案中的cas伺服器地址、本機地址和需要驗證的介面
- 通過request獲取即可
- cas伺服器
當用戶名登入不上時候,檢視cas伺服器命令列是否有異常。
參考: