1. 登录流程
登录流程分为以下步骤:
-
获取 TGT(Ticket Granting Ticket):
-
使用用户名和密码向 CAS 的
/cas/v1/tickets
接口发送 POST 请求,获取 TGT。
-
-
获取 ST(Service Ticket):
-
使用 TGT 向 CAS 的
/cas/v1/tickets/{TGT}
接口发送 POST 请求,获取 ST。
-
-
验证 ST:
-
使用 ST 向 CAS 的
/cas/p3/serviceValidate
接口发送 GET 请求,验证 ST 并获取用户属性。
-
2. 登出流程
登出流程分为以下步骤:
-
注销 TGT:
-
使用 TGT 向 CAS 的
/cas/v1/tickets/{TGT}
接口发送 DELETE 请求,注销 TGT。
-
-
注销 ST:
-
使用 ST 向 CAS 的
/cas/v1/tickets/{ST}
接口发送 DELETE 请求,注销 ST。
-
3. 调用 CAS REST API 的示例代码
示例中,关于客户端验证 CAS 服务器的 SSL 证书问题,使用的时临时解决方案
-
临时解决方案:使用 HTTP 或忽略 SSL 证书验证(仅用于测试)。
-
推荐解决方案:将 CAS 服务器的 SSL 证书导入客户端的信任库,或使用有效的 SSL 证书。
-
生产环境:建议使用有效的 SSL 证书,并确保客户端信任该证书。
package com.test.springboot; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; public class CasRestClient { private static final String CAS_BASE_URL = "https://localhost:8443/cas"; private static final String SERVICE_URL = "https://www.apereo.org"; public static void main(String[] args) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { // 1. 获取 TGT String tgt = getTgt("admin", "password"); System.out.println("TGT: " + tgt); // 2. 获取 ST String st = getSt(tgt, SERVICE_URL); System.out.println("ST: " + st); // 3. 验证 ST String userAttributes = validateSt(st, SERVICE_URL); System.out.println("User Attributes: " + userAttributes); // 4. 注销 ST logoutSt(st); System.out.println("ST logged out"); // 5. 注销 TGT logoutTgt(tgt); System.out.println("TGT logged out"); } private static String getTgt(String username, String password) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { String url = CAS_BASE_URL + "/v1/tickets"; HttpPost request = new HttpPost(url); request.setHeader("Content-Type", "application/x-www-form-urlencoded"); request.setEntity(new StringEntity("username=" + username + "&password=" + password)); try (CloseableHttpClient client = createInsecureHttpClient()) { HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() == 201) { return response.getFirstHeader("Location").getValue(); } else { throw new RuntimeException("Failed to get TGT: " + response.getStatusLine()); } } } private static String getSt(String tgt, String serviceUrl) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { String url = tgt; HttpPost request = new HttpPost(url); request.setHeader("Content-Type", "application/x-www-form-urlencoded"); request.setEntity(new StringEntity("service=" + serviceUrl)); try (CloseableHttpClient client = createInsecureHttpClient()) { HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { return EntityUtils.toString(response.getEntity()); } else { throw new RuntimeException("Failed to get ST: " + response.getStatusLine()); } } } private static String validateSt(String st, String serviceUrl) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { String url = CAS_BASE_URL + "/p3/serviceValidate?ticket=" + st + "&service=" + serviceUrl; HttpGet request = new HttpGet(url); try (CloseableHttpClient client = createInsecureHttpClient()) { HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { return EntityUtils.toString(response.getEntity()); } else { throw new RuntimeException("Failed to validate ST: " + response.getStatusLine()); } } } private static void logoutTgt(String tgt) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { String url = tgt; HttpDelete request = new HttpDelete(url); try (CloseableHttpClient client = createInsecureHttpClient()) { HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed to logout TGT: " + response.getStatusLine()); } } } private static void logoutSt(String st) throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { String url = CAS_BASE_URL + "/v1/tickets/" + st; HttpDelete request = new HttpDelete(url); try (CloseableHttpClient client = createInsecureHttpClient()) { HttpResponse response = client.execute(request); if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed to logout ST: " + response.getStatusLine()); } } } private static CloseableHttpClient createInsecureHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, KeyManagementException { // return HttpClients.createDefault(); SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, (certificate, authType) -> true) .build(); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); return HttpClients.custom() .setSSLSocketFactory(socketFactory) .build(); } }
4、CAS Service配置与管理
示例中使用的url时 SERVICE_URL = "https://www.apereo.org"
需要在cas服务的application.properties文件中配置
# JSON 文件来初始化服务注册表(默认false) cas.service-registry.init-from-json=true
并且拷贝service的json文件,将WEB-INF/classes/services目录拷贝到services中
5、Postman请求登录
1、获取TGT
2、获取ST
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 数据并发安全校验处理工具类