这个是5.2版本的,5.2和5.1有一点区别,但是区别不大,只是注册表单的地方,有点区别。自定义表单,为啥有这个需求呢,就比如我们表单不止需要有用户名,密码,还需要有系统的信息,这样,就需要自定义表单的方式来完成了这个是cas5.2.x版本,同5.1.x版本不适用。。

代码地址

https://gitee.com/yellowcong/springboot_cas/tree/master/cas-server-form/5.2.x/cas-server-form

目录结构

CAS之5.2.x版本自定义表单信息-yellowcong_表单

表单添加

1、创建表单

表单对象,需要继承默认的RememberMeUsernamePasswordCredential ,添加用户所需要的字段,我现在需要加上一个部门的字段信息。

package com.yellowcong.auth;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apereo.cas.authentication.RememberMeUsernamePasswordCredential;
import javax.validation.constraints.Size;

/**
 * 用户名,密码,系统
 * @author yellowcong
 * 创建日期:2018/02/06
 *
 */
public class UsernamePasswordSysCredential extends RememberMeUsernamePasswordCredential {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Size(min = 2, message = "require system")
    private String system;

    public String getSystem() {
        return system;
    }

    public UsernamePasswordSysCredential setSystem(String system) {
        this.system = system;
        return this;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().appendSuper(super.hashCode()).append(this.system).toHashCode();
    }
}

2、添加参数配置器

参数创建好了,需要配置到我们想要绑定的表单对象以及页面上。表单配置,需要继承AbstractCasWebflowConfigurer类,然后复写里面的doInitialize方法

package com.yellowcong.auth;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.CasWebflowConstants;
import org.apereo.cas.web.flow.configurer.AbstractCasWebflowConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;

/**
 * 重新定义默认的web流程
 * @author yellowcong
 * 创建日期:2018/02/06
 *
 */
public class CustomWebflowConfigurer extends AbstractCasWebflowConfigurer {

    public CustomWebflowConfigurer(FlowBuilderServices flowBuilderServices,
            FlowDefinitionRegistry loginFlowDefinitionRegistry, ApplicationContext applicationContext,
            CasConfigurationProperties casProperties) {
        super(flowBuilderServices, loginFlowDefinitionRegistry, applicationContext, casProperties);
    }

    @Override
    protected void doInitialize() {
          final Flow flow = getLoginFlow();
          bindCredential(flow);
    }

    /**
     * 绑定输入信息
     *
     * @param flow
     */
    protected void bindCredential(Flow flow) {
        //重写绑定自定义credential
        //表单对象,就是这个 credential 
        createFlowVariable(flow, CasWebflowConstants.VAR_ID_CREDENTIAL, UsernamePasswordSysCredential.class);

        //获取登录页
        final ViewState state = (ViewState) flow.getState(CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM);

        //获取参数绑定对象
        final BinderConfiguration cfg = getViewStateBinderConfiguration(state);

        //由于用户名以及密码已经绑定,所以只需对新加系统参数绑定即可
        //参数1 :字段名
        //参数2 :转换器
        //参数3 :是否必须的字段
        cfg.addBinding(new BinderConfiguration.Binding("system", null, false));
    }
}

3、配置到springboot中

在cas5.2.x版本和cas5.1.x版本,就这个地方有区别,而且表单配置的那个类,够着函数也是有所区别的。

package com.yellowcong.config;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.CasWebflowConfigurer;
import org.apereo.cas.web.flow.config.CasWebflowContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;

import com.yellowcong.auth.CustomWebflowConfigurer;

/**
 * @author Carl
 * @date 2017/10/23
 * @since 1.6.0
 */
@Configuration("customerAuthWebflowConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
@AutoConfigureBefore(value = CasWebflowContextConfiguration.class)
public class CustomerAuthWebflowConfiguration {
    @Autowired
    private CasConfigurationProperties casProperties;

    @Autowired
    @Qualifier("loginFlowRegistry")
    private FlowDefinitionRegistry loginFlowRegistry;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private FlowBuilderServices flowBuilderServices;

    /**
     * 注册我们的表单到服务器上
     * @return
     */
    @Bean
    public CasWebflowConfigurer customWebflowConfigurer() {
        //实例化自定义的表单配置类
        final CustomWebflowConfigurer c = new CustomWebflowConfigurer(flowBuilderServices, loginFlowRegistry,
                applicationContext, casProperties);
        //初期化
        c.initialize();
        //返回对象
        return c;
    }
}

表单验证器

1、创建表单处理类

需要继承AbstractPreAndPostProcessingAuthenticationHandler 这个类,这个地方我添加的规则是只要是UsernamePasswordSysCredential类型的表单,我们才能处理,而且处理逻辑是,用户名是yellowcong,系统是sso的,才可以登录

package com.yellowcong.auth.handler;

import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;

import com.yellowcong.auth.UsernamePasswordSysCredential;

import javax.security.auth.login.AccountNotFoundException;
import java.security.GeneralSecurityException;
import java.util.Collections;

/**
 * 用户名系统认证,只要是admin用户加上sso系统就允许通过
 * @author yellowcong
 * 创建日期:2018/02/06
 *
 */
public class UsernamePasswordSystemAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {
    public UsernamePasswordSystemAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
        super(name, servicesManager, principalFactory, order);
    }

    @Override
    protected HandlerResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
        //当用户名为admin,并且system为sso即允许通过
        UsernamePasswordSysCredential sysCredential = (UsernamePasswordSysCredential) credential;
        if ("yellowcong".equals(sysCredential.getUsername()) && "sso".equals(sysCredential.getSystem())) {
            //这里可以自定义属性数据
            return createHandlerResult(credential, this.principalFactory.createPrincipal(((UsernamePasswordSysCredential) credential).getUsername(), Collections.emptyMap()), null);
        } else {
            throw new AccountNotFoundException("必须是yellowcong这样的用户才允许通过");
        }
    }


    @Override
    public boolean supports(Credential credential) {
        return credential instanceof UsernamePasswordSysCredential;
    }
}

2、注册到springboot

注册验证器到springboot中。

package com.yellowcong.config;

import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
import org.apereo.cas.authentication.AuthenticationHandler;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.services.ServicesManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.yellowcong.auth.handler.UsernamePasswordSystemAuthenticationHandler;

/**
 * @author yellowcong
 * 创建日期:2018/02/06
 *
 */
@Configuration("customAuthenticationEventExecutionPlanConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CustomAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer {
    @Autowired
    @Qualifier("servicesManager")
    private ServicesManager servicesManager;

    /**
     * 注册验证器
     *
     * @return
     */
    @Bean
    public AuthenticationHandler customAuthenticationHandler() {
        //优先验证
        return new UsernamePasswordSystemAuthenticationHandler("customAuthenticationHandler",
                servicesManager, new DefaultPrincipalFactory(), 1);
    }

    //注册自定义认证器
    @Override
    public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
        plan.registerAuthenticationHandler(customAuthenticationHandler());
    }
}

添加到spring.factories

为了让springboot知道我们添加了哪些配置类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yellowcong.config.CustomerAuthWebflowConfiguration,\
com.yellowcong.config.CustomAuthenticationEventExecutionPlanConfiguration

启动服务

#普通方式启动
build.cmd run 

#debug方式启动
build.cmd debug

CAS之5.2.x版本自定义表单信息-yellowcong_单点登录_02

登录验证

我们从8888客户端登录系统,然后我们先用了yellowcong用户密码瞎打的,最后系统类型,没选单点登录,结果登录失败,如果用户名yellowcong,并且是sso系统,就可以直接扽登录了。

CAS之5.2.x版本自定义表单信息-yellowcong_spring_03

常见问题

1、找不到org.apereo.cas.configuration类

我只能说是个bug,需要单独导入这个包到系统中,就解决问题了

CAS之5.2.x版本自定义表单信息-yellowcong_cas_04

解决办法,就是导入一个jar包到工程目录。

<!-- 单独导入cas的配置依赖到项目中 -->
<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-core-configuration</artifactId>
    <version>${cas.version}</version>
    <scope>system</scope>
    <optional>true</optional>
    <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-core-configuration-${cas.version}.jar</systemPath>
</dependency>

2、Failed to clean project: Failed to delete

出现这个问题,就是target目录有占用,mvn的命令工具删除不掉里面的数据,所以只能手动解锁,删除里面的数据。

CAS之5.2.x版本自定义表单信息-yellowcong_ci_05

参考文章

https://apereo.github.io/cas/5.2.x/installation/Webflow-Customization-Extensions.html