CAS单点登录:动态添加service(四)

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

posted @ 2020-05-20 08:40  市井俗人  阅读(3115)  评论(0编辑  收藏  举报