cas5.3.2单点登录-自定义登录验证(四)

原文地址,转载请注明出处: https://blog.csdn.net/qq_34021712/article/details/81144874     ©王赛超 

我们在使用SSO单点登录的时候不只是验证一下用户名和密码是否一致,有时候还需要验证一些别的校验,那么这一张讲一下如何自定义验证器。
自定义验证很重要,因为我们后续的很多功能,都是基于自定义验证。
CAS服务器的org.apereo.cas.authentication.AuthenticationManager负责基于提供的凭证信息进行用户认证。与Spring Security很相似,实际的认证委托给了一个或多个实现了org.apereo.cas.authentication.AuthenticationHandler接口的处理类。在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。
CAS内置了一些AuthenticationHandler实现类,如下图所示,QueryDatabaseAuthenticationHandler中提供了基于jdbc的用户认证。
cas5.3.2单点登录-自定义登录验证(四)_第1张图片
如果需要实现自定义登录,只需要实现org.apereo.cas.authentication.AuthenticationHandler接口即可。当然也可以利用已有的实现,比如创建一个继承自org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler的类。下面我们就来实现自定义验证。

自定义验证

pom添加依赖

<dependency>
    <groupId>org.apereo.casgroupId>
    <artifactId>cas-server-core-authenticationartifactId>
    <version>${cas.version}version>
dependency>
<dependency>
    <groupId>org.apereo.casgroupId>
    <artifactId>cas-server-core-authentication-apiartifactId>
    <version>${cas.version}version>
dependency>
 <dependency>
    <groupId>org.apereo.casgroupId>
    <artifactId>cas-server-core-webflowartifactId>
    <version>${cas.version}version>
dependency>

自定义验证类,继承AbstractUsernamePasswordAuthenticationHandler

在此只验证是不是admin用户,其他用户不让登录。

package com.wangsaichao.cas.custom;

import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;

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

/**
 * @author: wangsaichao
 * @date: 2018/7/21
 * @description: 自定义验证器
 */
public class MyAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler{

    public MyAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
        super(name, servicesManager, principalFactory, order);
    }

    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException {

        if("admin".equals(credential.getUsername())){
            return createHandlerResult(credential,
                    this.principalFactory.createPrincipal(credential.getUsername()),
                    new ArrayList<>(0));
        }else{
            throw new AccountNotFoundException("必须是admin用户才允许通过");
        }
    }
}

注册验证器

package com.wangsaichao.cas.config;

import com.wangsaichao.cas.custom.MyAuthenticationHandler;
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;

/**
 * @author: wangsaichao
 * @date: 2018/7/21
 * @description: 注册验证器
 */
@Configuration("myAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class MyAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {


    @Autowired
    private CasConfigurationProperties casProperties;

    @Autowired
    @Qualifier("servicesManager")
    private ServicesManager servicesManager;

    /**
     * 将自定义验证器注册为Bean
     * @return
     */
    @Bean
    public AuthenticationHandler myAuthenticationHandler() {
        MyAuthenticationHandler handler = new MyAuthenticationHandler(MyAuthenticationHandler.class.getSimpleName(), servicesManager, new DefaultPrincipalFactory(), 1);
        return handler;
    }

    /**
     * 注册验证器
     * @param plan
     */
    @Override
    public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
        plan.registerAuthenticationHandler(myAuthenticationHandler());
    }
}

加载该配置类

在resources\META-INF\spring.factories中配置该类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangsaichao.cas.config.MyAuthenticationConfiguration

测试

使用test/123456登录
注意:结果可能很奇怪,使用test竟然可以登录,那我们自定义验证器有什么用呢?上面我们说了:在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。也就是说在执行的过程中,肯定有一个authenticationHandlers执行成功了,通过debug发现,PolicyBasedAuthenticationManager中如下截图:
cas5.3.2单点登录-自定义登录验证(四)_第2张图片
为什么会出现这种情况,还记得我们上一篇博客中配置jdbc验证,以及密码加盐处理,在application.properties中有配置以下两中开头的配置:
cas.authn.jdbc.query[0].* 和 cas.authn.jdbc.encode[0].*
分别对应了:QueryDatabaseAuthenticationHandler 和 QueryAndEncodeDatabaseAuthenticationHandler 其中使用test/123456用户登录QueryAndEncodeDatabaseAuthenticationHandler这个处理器执行成功了,所以就登录成功。

所以我们在使用自定义验证器的时候,查询数据库操作,要自己实现,而不能使用cas自带的,包括密码加密等。

再次测试

将application.properties中jdbc相关 和 密码加盐相关配置注释, 再次使用admin 和 test 账户测试。密码随便写,因为并没有走数据库校验。
admin可以登录。
test不可以登录,认证失败。

你可能感兴趣的:(cas,CAS学习)