CAS-5.2.6单点登录-自定义验证策略

SSO单点登录的时候不只是验证一下用户名和密码是否一致,有时候还需要验证一些别的校验,之就需要我们进行自定义验证。具体查看官网文档说明。

https://apereo.github.io/cas/5.2.x/installation/Configuring-Custom-Authentication.html#overview

    CAS服务器的org.apereo.cas.authentication.AuthenticationManager负责基于提供的凭证信息进行用户认证。实际的认证委托给了一个或多个实现了org.apereo.cas.authentication.AuthenticationHandler接口的处理类。在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。 CAS内置了一些AuthenticationHandler实现类 。

   身份验证处理程序本身定义框架。这是核心主要组件,其作用是声明对给定类型的凭证的支持,然后尝试验证它并生成成功的结果。所有处理程序扩展的核心父组件是AuthenticationHandler接口。

因而自定义验证器继承其中任意个重写里面相应的方法或者实现AuthenticationHandler接口也可以。并且 应为是自定义的登陆控制器,所以我们需要重写数据库链接,如果不重写,cas还是默认使用的是在application.properties中有配置以下两中开头的配置: cas.authn.jdbc.query[0].* 和 cas.authn.jdbc.encode[0].* 分别对应了:QueryDatabaseAuthenticationHandler 和 QueryAndEncodeDatabaseAuthenticationHandler .

重写数据库链接方式:

修改application.properties配置链接数据库方式:

##########################################################JDBC验证##############################################################################
#
##Query Database Authentication 数据库查询校验用户名开始
##查询账号密码sql,必须包含密码字段
##数据库查询用户名语句,其中user_info对应表名,username对应登录账号的字段名
#cas.authn.jdbc.query[0].sql=SELECT * FROM user_info WHERE username =?
##指定上面的sql查询字段名(必须)
#cas.authn.jdbc.query[0].fieldPassword=password
##指定过期字段,1为过期,若过期不可用(可选)
##cas.authn.jdbc.query[0].fieldExpired=expired
##为不可用字段段,1为不可用,需要修改密码(可选)
##cas.authn.jdbc.query[0].fieldDisabled=disabled
##数据库方言hibernate的
#cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
##数据库驱动
#cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
##数据库连接
#cas.authn.jdbc.query[0].url=jdbc:mysql://ddd:3306/test?useUnicode=true&characterEncoding=UTF-8
##数据库用户名
#cas.authn.jdbc.query[0].user=root
##数据库密码
#cas.authn.jdbc.query[0].password=ddd
##默认加密策略,通过encodingAlgorithm来指定算法,默认NONE不加密
##cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT 自定义加密策略
#cas.authn.jdbc.query[0].passwordEncoder.type=com.cas.passwordEncode.MyEncoder
#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
##Query Database Authentication 数据库查询校验用户名结束
###########################################################JDBC验证 加盐##############################################################################
#
##加密迭代次数
#cas.authn.jdbc.encode[0].numberOfIterations=2
##该列名的值可替代上面的值,但对密码加密时必须取该值进行处理
#cas.authn.jdbc.encode[0].numberOfIterationsFieldName=
##盐值固定列 盐值
#cas.authn.jdbc.encode[0].saltFieldName=username
##静态盐值
#cas.authn.jdbc.encode[0].staticSalt=.
#cas.authn.jdbc.encode[0].sql=SELECT * FROM user_info WHERE username =?
##对处理盐值后的算法
#cas.authn.jdbc.encode[0].algorithmName=MD5
#cas.authn.jdbc.encode[0].passwordFieldName=password
#cas.authn.jdbc.encode[0].expiredFieldName=expired
#cas.authn.jdbc.encode[0].disabledFieldName=disabled
##数据库连接
#cas.authn.jdbc.encode[0].url=jdbc:mysql://ddd:3306/test?useUnicode=true&characterEncoding=UTF-8
#cas.authn.jdbc.encode[0].dialect=org.hibernate.dialect.MySQL5Dialect
#cas.authn.jdbc.encode[0].driverClass=com.mysql.jdbc.Driver
#cas.authn.jdbc.encode[0].user=root
#cas.authn.jdbc.encode[0].password=ddd

#注意:如果两种方式都配置的话,默认先用普通MD5验证,如果验证失败,打印异常日志,然后再使用加盐方式验证。

##########################################################spring boot自动配置数据原##############################################################################

#下面所是数据源,让spring boot自动配置,默认cas屏蔽了spring boot自动配置,下面的代码中我们在spring boot扫描的目录中开启这个配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://dddd:3306/test?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=dddd
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource

spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

#连接池配置
##初始化连接:连接池启动时创建的初始化连接数量
spring.datasource.dbcp2.initial-size=5
#最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制
spring.datasource.dbcp2.max-active=1000
#最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制
spring.datasource.dbcp2.max-idle=100
#从连接池获取一个连接时,最大的等待时间,设置为-1时,如果没有可用连接,连接池会一直无限期等待,直到获取到连接为止。
#如果设置为N(毫秒),则连接池会等待N毫秒,等待不到,则抛出异常
spring.datasource.dbcp2.max-wait-millis=60000
#通过这个池创建连接的默认自动提交状态。如果不设置,则setAutoCommit 方法将不被调用
spring.datasource.dbcp2.default-auto-commit=true
#通过这个池创建连接的默认只读状态。如果不设置,则setReadOnly  方法将不被调用。(部分驱动不支持只读模式,如:Informix)
spring.datasource.dbcp2.default-read-only=false
#指明在从池中租借对象时是否要进行验证有效,如果对象验证失败,则对象将从池子释放,然后我们将尝试租借另一个
spring.datasource.dbcp2.test-on-borrow=true

#自定义属性 这些属性我们在jdbc验证的时候需要
#用户名,密码查询
user.password.query.sql = SELECT * FROM user_info WHERE username =?

修改成spring boot默认配置数据源方式。

自定义登陆验证:


package com.cas.authentication;


import com.cas.passwordEncode.MyEncoder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.dao.DataAccessException;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;

import javax.security.auth.login.AccountNotFoundException;
import java.security.GeneralSecurityException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * @Project casspringboot
 * @Package com.cas
 * @ClassName MyUserNamePasswordAuthenticationHandler
 * @Descripition TODO
 * @Author able
 * @Date 2019/6/13 15:55
 * @Version 1.0
 **/

public  class MyUserNamePasswordAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {

    /**
     * 为了符合cacheService key的名称定义格式。
     */
    public static final String CSUFFIX_USERLOGIN = "_2ae941e8-21e5-4013-9568-4dcee975333a";

    /**
     * 根据用户名和密码查询sql语句
     */
    @Value("${user.password.query.sql}")
    private String userQuerySql;


    /**
     * jdbc模板
     */
    @Autowired
    private JdbcTemplate jdbcTemplate;

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

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

        if("admin".equals(credential.getUsername())){
            List<Userinfo> list = new ArrayList();
             jdbcTemplate.query(userQuerySql, new PreparedStatementSetter() {
                public void setValues(PreparedStatement ps) throws SQLException {
                    ps.setString(1, credential.getUsername());
                }
            }, new ResultSetExtractor() {
                public Object extractData(ResultSet rs) throws SQLException, DataAccessException {

                    while (rs.next()) {

                        Userinfo u = new Userinfo();

                        u.setId(rs.getInt("id"));

                        u.setUsername(rs.getString("username"));

                        u.setPassword(rs.getString("password"));

                        u.setName(rs.getString("name"));
                        list.add(u);
                    }
                    return list;
                }
            });

             if(CollectionUtils.isNotEmpty(list)){

                 Userinfo o = list.get(0);

                 System.out.println(o);


             }
            //TODO 相关业务胜率
            return createHandlerResult(credential,
                    this.principalFactory.createPrincipal(credential.getUsername()),
                    new ArrayList<>(0));
        }else{
            throw new AccountNotFoundException("必须是admin用户才允许通过");
        }
    }
}

注册验证器:

package com.cas.authentication;

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.authentication.principal.PrincipalFactory;
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.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/*
 * @Project casspringboot
 * @Package com.cas.authentication
 * @ClassName AuthenticationConfig
 * @Descripition 注册自定义验证器
 * @Author able
 * @Date 2019/6/13 17:17
 * @Version 1.0
 */
//增加了@Import({DataSourceAutoConfiguration.class}),开启Spring Boot数据源自动配置,这样才可以使用使用jdbcTemplate
@Import({DataSourceAutoConfiguration.class})
@Configuration("myAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class AuthenticationConfig implements AuthenticationEventExecutionPlanConfigurer {

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

    @Autowired
    @Qualifier("jdbcPrincipalFactory")
    public PrincipalFactory jdbcPrincipalFactory;


     /*
     * 注册验证器
     *
     * @return
     */

    @Bean
    public AuthenticationHandler customAuthenticationHandler() {
        //优先验证
        MyUserNamePasswordAuthenticationHandler handler = new MyUserNamePasswordAuthenticationHandler(MyUserNamePasswordAuthenticationHandler.class.getSimpleName(), servicesManager, new DefaultPrincipalFactory(), 1);
        return handler;

    }

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

加载该配置类

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

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration,\
  com.cas.authentication.AuthenticationConfig

测试:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值