1.簡介
在CAS系統中,主要分為三部分,User、Web應用、SSO認證中心。
User就是我們普通用戶,Web應用就是需要接入SSO認證中心的應用也就是這里的Service,而SSO認證中心就是CAS服務端。
簡單來說就是CAS分為服務端和客戶端,而Service就是指具體的多個客戶端(CAS Clients)。
我們整合客戶端的時候,需要在cas服務端注冊,使用的是json文件的方式。不是很方便,這里我們提供接口,動態操作。
2.引入依賴
修改pom.xml,如下:
<dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jpa-service-registry</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-core-services-api</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-core-authentication-attributes</artifactId> <version>${cas.version}</version> </dependency> <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>5.1.36</version> </dependency>
排除war包自帶的兩個json,添加節點:dependentWarExcludes
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <warName>cas</warName> <failOnMissingWebXml>false</failOnMissingWebXml> <recompressZippedFiles>false</recompressZippedFiles> <archive> <compress>false</compress> <manifestFile>${manifestFileToUse}</manifestFile> </archive> <overlays> <overlay> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp${app.server}</artifactId> </overlay> </overlays> <dependentWarExcludes> **/services/*.json </dependentWarExcludes> </configuration> </plugin>
3.application.properties添加以下屬性
第一次啟動使用create-drop,二次運行時改為update
## # Jpa配置 # cas.serviceRegistry.jpa.user=root cas.serviceRegistry.jpa.password=123456 cas.serviceRegistry.jpa.driverClass=com.mysql.jdbc.Driver cas.serviceRegistry.jpa.url=jdbc:mysql://127.0.0.1:3306/cas?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false cas.serviceRegistry.jpa.dialect=org.hibernate.dialect.MySQL5Dialect #連接池配置 cas.serviceRegistry.jpa.pool.suspension=false cas.serviceRegistry.jpa.pool.minSize=6 cas.serviceRegistry.jpa.pool.maxSize=18 cas.serviceRegistry.jpa.pool.maxWait=2000 cas.serviceRegistry.jpa.pool.timeoutMillis=1000 #設置配置的服務,一直都有,不會給清除掉,第一次使用,需要配置為 create-drop #create-drop 重啟cas服務的時候,就會給干掉 #create 沒有表就創建,有就不創建 #none 一直都有 #update 更新 cas.serviceRegistry.jpa.ddlAuto=create-drop
4.添加rest接口
其實主要是使用ServiceManager中的接口,包名:org.apereo.cas.services.ServicesManager
public interface ServicesManager { RegisteredService save(RegisteredService registeredService); RegisteredService save(RegisteredService registeredService, boolean publishEvent); void deleteAll(); RegisteredService delete(long id); RegisteredService delete(RegisteredService svc); RegisteredService findServiceBy(String serviceId); RegisteredService findServiceBy(Service service); Collection<RegisteredService> findServiceBy(Predicate<RegisteredService> clazz); <T extends RegisteredService> T findServiceBy(Service serviceId, Class<T> clazz); <T extends RegisteredService> T findServiceBy(String serviceId, Class<T> clazz); RegisteredService findServiceBy(long id); Collection<RegisteredService> getAllServices(); boolean matchesExistingService(Service service); boolean matchesExistingService(String service); Collection<RegisteredService> load(); default int count() { return 0; } default Collection<RegisteredService> getServicesForDomain(String domain) { return this.getAllServices(); } default Collection<String> getDomains() { return (Collection)Stream.of("default").collect(Collectors.toList()); } }
接口的具體實現類:
import com.fdzang.cas.service.domain.ServiceDO; import com.fdzang.cas.service.framework.ApiResult; import com.fdzang.cas.service.framework.BaseController; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.services.RegexRegisteredService; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.ReturnAllAttributeReleasePolicy; import org.apereo.cas.services.ServicesManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.*; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Slf4j @RestController @RequestMapping("/service") public class ServiceController extends BaseController { @Autowired @Qualifier("servicesManager") private ServicesManager servicesManager; @PostMapping public ApiResult addService(@RequestBody ServiceDO service) throws Exception { RegisteredService registeredService = findByServiceId(service.getServiceId()); if (registeredService != null) { return fail("serviceId:" + service.getServiceId() + " 已存在"); } RegexRegisteredService regexRegisteredService = covertService(service); servicesManager.save(regexRegisteredService, true); servicesManager.load(); registeredService = findByServiceId(service.getServiceId()); return ok(covertRegisteredService(registeredService)); } @DeleteMapping public ApiResult delService(@RequestParam("serviceId") String serviceId) { boolean flag = false; RegisteredService registeredService = findByServiceId(serviceId); if (registeredService != null) { try { servicesManager.delete(registeredService); } catch (Exception e) { //這里會報審計錯誤,直接進行捕獲即可,不影響刪除邏輯 log.error(e.getMessage()); } if (null == findByServiceId(serviceId)) { servicesManager.load(); flag = true; } }else{ return fail("serviceId:" + serviceId + " 不存在"); } if (flag){ return ok("刪除成功"); }else{ return fail("刪除失敗"); } } @GetMapping("/all") public ApiResult getAllService() { Collection<RegisteredService> allServices = servicesManager.getAllServices(); return ok(covertRegisteredServiceList(allServices)); } @GetMapping public ApiResult getByServiceId(@RequestParam("serviceId") String serviceId) { RegisteredService service = findByServiceId(serviceId); return ok(covertRegisteredService(service)); } private ServiceDO covertRegisteredService(RegisteredService registeredService) { ServiceDO service = new ServiceDO(); service.setServiceId(registeredService.getServiceId()); service.setDescription(registeredService.getDescription()); service.setEvaluationOrder(registeredService.getEvaluationOrder()); service.setId(registeredService.getId()); service.setName(registeredService.getName()); service.setTheme(registeredService.getTheme()); return service; } private List<ServiceDO> covertRegisteredServiceList(Collection<RegisteredService> registeredServices) { if (CollectionUtils.isEmpty(registeredServices)) { return null; } List<ServiceDO> services = new ArrayList<>(); for (RegisteredService registeredService : registeredServices) { services.add(covertRegisteredService(registeredService)); } return services; } private RegexRegisteredService covertService(ServiceDO service) throws Exception { RegexRegisteredService regexRegisteredService = new RegexRegisteredService(); String serviceId = "^(https|imaps|http)://" + service.getServiceId() + ".*"; ReturnAllAttributeReleasePolicy returnAllAttributeReleasePolicy = new ReturnAllAttributeReleasePolicy(); regexRegisteredService.setServiceId(serviceId); regexRegisteredService.setId(service.getId()); regexRegisteredService.setDescription(service.getDescription()); regexRegisteredService.setEvaluationOrder(service.getEvaluationOrder()); if (StringUtils.isNotBlank(service.getTheme())) { regexRegisteredService.setTheme(service.getTheme()); } regexRegisteredService.setAttributeReleasePolicy(returnAllAttributeReleasePolicy); regexRegisteredService.setName(service.getName()); regexRegisteredService.setLogoutUrl(new URL("http://" + service.getServiceId())); return regexRegisteredService; } public RegisteredService findByServiceId(String serviceId){ RegisteredService service = null; serviceId = "http://" + serviceId; try { service = servicesManager.findServiceBy(serviceId); } catch (Exception e) { log.error(e.getMessage()); } return service; } }
這個地方,我自定義了ServiceDO用來數據的接收及展示。
自定義了ApiResult,統一返回結果。
5.添加包掃描配置
cas項目,其實也是集成的Springboot,這里我們自定義注解完成包掃描工作,后續新的類加進來,無需再修改spring.factories
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.fdzang.cas") public class SpringConfig { }
修改spring.factories,加入我們的包掃描配置。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration,\
org.apereo.cas.config.CasEmbeddedContainerTomcatFiltersConfiguration,\
com.fdzang.cas.service.config.SpringConfig
參考:https://blog.csdn.net/qq_34021712/article/details/81638090