0.說明
本系列文章只根據自己的需要做部分定制,完整的教程見:https://blog.csdn.net/qq_34021712/category_9278675.html
有興趣的可以一起研究。
1.服務端
1.1.Service配置
客戶端接入 CAS 首先需要在服務端進行注冊,否則客戶端訪問將提示“未認證授權的服務”警告:
簡單需求:對所有https和http請求的service進行允許認證。
在resources/services下新建文件fdzang-1000.json,這個文件是我根據cas源代碼HTTPSandIMAPS-10000001.json更改的。路徑:cas\WEB-INF\classes\services
{ "@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "^(https|imaps|http)://.*", "name": "fdzang", "id": 1000, "description": "CAS-SSO 登入", "evaluationOrder": 10000 }
注意:
services目錄中可包含多個 JSON 文件,其命名必須:${name}-${id}.json,id必須為json文件中內容id一致
對其中屬性的說明如下,更多詳細內容見:官方文檔-Service-Management。
- @class:必須為org.apereo.cas.services.RegisteredService的實現類
- serviceId:對服務進行描述的表達式,可用於匹配一個或多個 URL 地址
- name: 服務名稱
- id:全局唯一標志
- description:服務描述,會顯示在默認登錄頁
- evaluationOrder:定義多個服務的執行順序
1.2.修改application.properties
配置好service之后,根據官方文檔-service-registry,還需修改 application.properties 文件告知 CAS 服務端從本地加載服務定義文件
# 注冊客戶端
cas.serviceRegistry.initFromJson=true
2.自定義client-starter
2.1.創建項目
創建一個springboot項目,pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fdzang</groupId> <artifactId>cas-client-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> <!-- 引用依賴的父包 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <!-- 配置該插件將源碼放入倉庫 --> <plugin> <artifactId>maven-source-plugin</artifactId> <version>2.1</version> <configuration> <attach>true</attach> </configuration> <executions> <execution> <phase>compile</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2.2.加載配置文件
這個類主要的作用是讀取client端application.yml中,關於cas相關的配置
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import javax.validation.constraints.NotNull; @Data @ConfigurationProperties(prefix = "cas", ignoreUnknownFields = false) public class CasClientConfigurationProperties { /** * CAS 服務端 url 不能為空 */ @NotNull private String serverUrlPrefix; /** * CAS 服務端登錄地址 上面的連接 加上/login 該參數不能為空 */ @NotNull private String serverLoginUrl; /** * 當前客戶端的地址 */ @NotNull private String serverName; /** * 忽略規則,訪問那些地址 不需要登錄 */ private String ignorePattern; /** * 認證的URL */ private String authrizationUrl; }
2.3.編寫AutoConfigure配置類
這些自動注入的配置,能夠讓客戶端實現接入cas。
import org.jasig.cas.client.authentication.AuthenticationFilter; import org.jasig.cas.client.session.SingleSignOutFilter; import org.jasig.cas.client.session.SingleSignOutHttpSessionListener; import org.jasig.cas.client.util.AssertionThreadLocalFilter; import org.jasig.cas.client.util.HttpServletRequestWrapperFilter; import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import java.util.EventListener; import java.util.HashMap; import java.util.Map; @Configuration @EnableConfigurationProperties(CasClientConfigurationProperties.class) public class CasClientConfiguration { @Autowired CasClientConfigurationProperties configProps; @Bean public FilterRegistrationBean filterSingleRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new SingleSignOutFilter()); registration.addUrlPatterns("/*"); registration.setOrder(1); Map<String, String> params = new HashMap<String, String>(); params.put("casServerUrlPrefix", configProps.getServerUrlPrefix()); params.put("serverName", configProps.getServerName()); registration.setInitParameters(params); return registration; } @Bean public ServletListenerRegistrationBean<EventListener> singleSignOutListenerRegistration() { ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<EventListener>(); registrationBean.setListener(new SingleSignOutHttpSessionListener()); registrationBean.setOrder(1); return registrationBean; } @Bean public FilterRegistrationBean filterAuthenticationRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new AuthenticationFilter()); registration.addUrlPatterns("/*"); registration.setOrder(2); Map<String, String> params = new HashMap<String, String>(); params.put("casServerLoginUrl", configProps.getServerLoginUrl()); params.put("serverName", configProps.getServerName()); if (!StringUtils.isEmpty(configProps.getIgnorePattern())) { params.put("ignorePattern", configProps.getIgnorePattern()); } registration.setInitParameters(params); return registration; } @Bean public FilterRegistrationBean filterValidationRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter()); registration.addUrlPatterns("/*"); registration.setOrder(3); Map<String, String> params = new HashMap<String, String>(); params.put("casServerUrlPrefix", configProps.getServerUrlPrefix()); params.put("serverName", configProps.getServerName()); params.put("useSession", "true"); registration.setInitParameters(params); return registration; } @Bean public FilterRegistrationBean filterWrapperRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new HttpServletRequestWrapperFilter()); registration.addUrlPatterns("/*"); registration.setOrder(4); return registration; } @Bean public FilterRegistrationBean casAssertionThreadLocalFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new AssertionThreadLocalFilter()); registration.addUrlPatterns("/*"); registration.setOrder(5); return registration; } }
2.4.編譯基於注解啟動方式
客戶端只需要在啟動類上加上@EnableCasClient注解即可實現接入cas
import org.springframework.context.annotation.Import; import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(CasClientConfiguration.class) public @interface EnableCasClient { }
3.客戶端
3.1.新建項目
新建一個springboot項目,pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fdzang</groupId> <artifactId>cas-client</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.9.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.cas.client.version>3.5.0</java.cas.client.version> </properties> <dependencies> <dependency> <groupId>com.fdzang</groupId> <artifactId>cas-client-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
3.2.配置文件application.yml
server:
port: 8082
cas:
server-url-prefix: https://server.cas.com:8443/cas
server-login-url: https://server.cas.com:8443/cas/login
server-name: http://127.0.0.1:8082
3.3.主啟動類
import com.fdzang.cas.client.configuration.EnableCasClient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableCasClient public class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); } }
3.4.測試接口
import com.fdzang.cas.client.configuration.CasClientConfigurationProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RestController public class UserController { @Autowired CasClientConfigurationProperties configProps; @GetMapping("/login") public String login(HttpServletRequest request, HttpServletResponse response) throws IOException { String username = request.getRemoteUser(); return username; } @GetMapping("/logout") public void loginOut(HttpServletRequest request, HttpServletResponse response) throws IOException { String url = configProps.getServerUrlPrefix() + "/logout?service=" + configProps.getServerName(); response.sendRedirect(url); } }