CAS 5.3自定义 登录

2023-11-12

自定义认证校验策略
我们知道CAS为我们提供了多种认证数据源,我们可以选择JDBC、File、JSON等多种方式,但是如果我想在自己的认证方式中可以根据提交的信息实现不同数据源选择,这种方式就需要我们去实现自定义认证。

自定义策略主要通过现实更改CAS配置,通过AuthenticationHandler在CAS中设计和注册自定义身份验证策略,拦截数据源达到目的。

主要分为下面三个步骤:

设计自己的认证处理数据的程序
注册认证拦截器到CAS的认证引擎中
更改认证配置到CAS中
首先我们还是添加需要的依赖库:

   <!-- Custom Authentication -->
    <dependency>
        <groupId>org.apereo.cas</groupId>
        <artifactId>cas-server-core-authentication-api</artifactId>
        <version>${cas.version}</version>
    </dependency>

    <!-- Custom Configuration -->
    <dependency>
        <groupId>org.apereo.cas</groupId>
        <artifactId>cas-server-core-configuration-api</artifactId>
        <version>${cas.version}</version>
    </dependency>

    <!-- SpringSecurity Core -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>5.0.8.RELEASE</version>
    </dependency>

如果我们认证的方式仅仅是传统的用户名和密码,实现AbstractUsernamePasswordAuthenticationHandler这个抽象类就可以了,官方
给的实例也是这个。

在编写自定义认证类之前,我们这里说明下为什么选择使用springSecurity提供的加解密工具类:BCryptPasswordEncoder

BCryptPasswordEncoder相关知识:
用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。
特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。
BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
补充说明:即使不同的用户注册时输入相同的密码,存入数据库的密文密码也会不同。

官方的实例有一个坑,给出的是5.2.x版本以前的例子,5.3.x版本后的jar包更改了,而且有个地方有坑,在5.2.x版本前的可以,新的5.3.x是不行的。

注意:这里试了很多版本最后 5.3.9这个版本没问题

接着我们自定义我们自己的实现类CustomUsernamePasswordAuthentication,如下:

package com.thtf.cas.config;

import com.thtf.cas.model.User;
import com.thtf.cas.util.SpringSecurityUtil;
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.MessageDescriptor;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.security.auth.login.AccountException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**

  • ========================

  • 自定义认证校验策略

  • Created with IntelliJ IDEA.

  • User:pyy

  • Date:2019/6/26

  • Time:16:05

  • Version: v1.0

  • ========================
    */
    public class CustomUsernamePasswordAuthentication extends AbstractUsernamePasswordAuthenticationHandler {

    private final static Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthentication.class);

    private JdbcTemplate jdbcTemplate;

    public CustomUsernamePasswordAuthentication(String name, ServicesManager servicesManager,
    PrincipalFactory principalFactory, Integer order, JdbcTemplate jdbcTemplate) {
    super(name, servicesManager, principalFactory, order);
    this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
    UsernamePasswordCredential credential, String originalPassword)
    throws GeneralSecurityException, PreventedException {
    String username = credential.getUsername();
    String password = credential.getPassword();
    logger.info(“认证用户 username = {}”, username);

     String sql = "select id, username, password, expired, disable, email FROM sys_user where username = ?";
     User info = (User) jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class));
     if (info == null) {
         logger.info("用户不存在!");
         throw new AccountException("用户不存在!");
     }
    
     if (!SpringSecurityUtil.checkpassword(password, info.getPassword())) {
         logger.info("密码错误!");
         throw new FailedLoginException("密码错误!");
     } else {
         logger.info("校验成功");
         //可自定义返回给客户端的多个属性信息
         HashMap<String, Object> returnInfo = new HashMap<>();
         returnInfo.put("id", info.getId());
         returnInfo.put("username", info.getUsername());
         returnInfo.put("expired", info.getExpired());
         returnInfo.put("disable", info.getDisable());
         returnInfo.put("email", info.getEmail());
         final List<MessageDescriptor> list = new ArrayList<>();
         return createHandlerResult(credential, this.principalFactory.createPrincipal(username, returnInfo), list);
     }
    

    }
    }

这里给出的与官方实例不同在两个地方:

返回的为 AuthenticationHandlerExecutionResult而不是HandlerResult,其实源码是一样的,在新版本重新命名了而已。
createHandlerResult传入的warings不能为null,不然程序运行后提交信息始终无法认证成功!!!
代码主要通过拦截传入的Credential,获取用户名和密码,然后再自定义返回给客户端的用户信息。这里便可以通过代码方式自定义返回给客户端多个不同属性信息。

注入配置信息
继承AuthenticationEventExecutionPlanConfigurer

package com.thtf.cas.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 org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

@Configuration(“CustomAuthenticationConfiguration”)
@EnableConfigurationProperties({CasConfigurationProperties.class, DataBaseProperties.class})
public class CustomAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {

@Autowired
private DataBaseProperties databaseProperties;

@Autowired
private JdbcTemplate jdbcTemplate;

@Autowired
private CasConfigurationProperties casProperties;

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

@Bean 
public AuthenticationHandler myAuthenticationHandler() { 
    return new CustomUsernamePasswordAuthentication(CustomUsernamePasswordAuthentication.class.getName(), servicesManager, new DefaultPrincipalFactory(), 1, jdbcTemplate); 
}

@Override
public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
    plan.registerAuthenticationHandler(myAuthenticationHandler());
}

@Bean
public JdbcTemplate jdbcTemplate(){
    // JDBC模板依赖于连接池来获得数据的连接,所以必须先要构造连接池 
    DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
    dataSource.setDriverClassName(databaseProperties.getDriverClass()); 
    dataSource.setUrl(databaseProperties.getUrl()); 
    dataSource.setUsername(databaseProperties.getUser()); 
    dataSource.setPassword(databaseProperties.getPassword()); 
    // 创建JDBC模板 
    JdbcTemplate jdbcTemplate = new JdbcTemplate(); 
    jdbcTemplate.setDataSource(dataSource); 
    return jdbcTemplate;
}

}

这里涉及到JdbcTemplate数据源配置如下:
数据源配置:

########## 用户认证JDBC数据源配置 ############
sso.jdbc.user=root
sso.jdbc.password=123456
sso.jdbc.driverClass=com.mysql.jdbc.Driver
sso.jdbc.url=jdbc:mysql://localhost:3306/sso?characterEncoding=utf8
DataBaseProperties:

package com.thtf.cas.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.Serializable;

@Component
@ConfigurationProperties(prefix = “sso.jdbc”)
@Data
public class DataBaseProperties implements Serializable {

private String user;

private String password;

private String driverClass;

private String url;

}
最后我们我们在src/main/resources目录下新建META-INF目录,同时在下面新建spring.factories文件,将配置指定为我们自己新建的信息。

启动应用,输入用户名和密码,查看控制台我们打印的信息,可以发现我们从登陆页面提交的数据以及从数据库中查询到的数据,匹配信息,登录认证成功!!

从而现实了我们自定义用户名和密码的校验,同时我们还可以选择不同的数据源方式。

补充
可能还有读者提出疑问,我提交的信息不止用户名和密码,那该如何自定义认证?
这里就要我们继承AbstractPreAndPostProcessingAuthenticationHandler这个借口,其实上面的AbstractUsernamePasswordAuthenticationHandler就是继承实现的这个类,它只是用于简单的用户名和密码的校验。我们可以查看源码,如下:

参考:https://www.jianshu.com/p/54646ac96473

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CAS 5.3自定义 登录 的相关文章

随机推荐

  • Wireshark网络抓包之抓取聊天网络数据包

    目录 一 抓包工具 1 Wireshark 2 Wireshark工作流程 二 抓取聊天网络数据包 1 设备连接 2 使用wireshark进行抓包 3 测试分析 三 总结 四 参考链接 一 抓包工具 1 Wireshark Wiresha
  • 【IntelliJ IDEA】idea不能实时编译,无法加载主类等情况

    前言 很多小伙伴使用idea的时候老是会遇到以下几种情况 如果有的呢就可以尝试我自己亲身测试的几个解决办法 代码总是不能实时编译 把代码内容修改之后 还是运行之前的代码 在一台电脑上运行的项目 通过git或者SVN的方式换到另一台电脑 就出
  • MySQL——命令行客户端的字符集问题

    原因 服务器端认为你的客户端的字符集是utf 8 而实际上你的客户端的字符集是GBK 查看所有字符集 SHOW VARIABLES LIKE character set 解决方案 设置当前连接的客户端字符集 SET NAMES GBK
  • 用户和用户组管理

    一 用户账号添加命令 useradd或adduser 介绍 useradd和adduser是完全等价的两条命令 都是用于创建新的用户账号 以useradd为例介绍 格式 useradd op username 选项 举例 useradd c
  • 谈冒烟测试与随机测试

    谈冒烟测试与随机测试来自51testing网 软件测试的种类何其多也 每种测试都有其要达到的目的和实现手段 本文将介绍两种不太普遍的测试类型 冒烟测试与随机测试 冒烟测试 冒烟测试 smoke testing 据说是微软起的名字 在 微软项
  • Ubuntu16.04 完全卸载cuda

    sudo apt get purge remove cuda
  • 解决GO语言编译程序在openwrt(mipsle架构)上运行提示Illegal instruction问题

    RT 最近在研究openwrt mipsle架构 上运行go语言编译出来的程序 一运行就报 Illegal instruction 这样的错误 百度和Google搜索了一遍 得出两种解决方案 PS 更新一遍 当时写这个文档的时候没有发现Go
  • JavaScript(6)-字符串的定义和使用,字符串的属性和方法及Math

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 字符串的定义和使用 1 字符串的定义 2 new String 和String 的区别 二 字符串的属性和方法 1 字符串的属性 2 字符串的方法 函数
  • 软件测试DAY02

    黑盒测试定义 黑盒测试相对于白盒测试而言 并不关心被测对象的内部实现 而是针对被测对象提供的外部功能与规格来设计测试用例进行的测试 黑盒测试分类 功能测试 性能测试 可用性测试 可靠性测试 安全性测试 客服务性测试 组网解决方案测试 常见黑
  • 贝叶斯分类算法及其matlab代码

    贝叶斯分类是一类分类算法的总称 这类算法均以贝叶斯定理为基础 故统称为贝叶斯分类 贝叶斯分类是一类利用概率统计知识进行分类的算法 其分类原理是贝叶斯定理 贝叶斯定理是由18世纪概率论和决策论的早期研究者Thomas Bayes发明的 故用其
  • Error:(x, xx) java: 找不到符号符号:类 xxx位置:程序包 xxx.xxx,只能通过mvn idea:module重新构建.iml文件

    程序运行时报找不到包类错误 折腾了一整天 最后只找到了临时解决办法 删除项目 项目名称 iml文件 通过 mvn idea module命令重新生成一个 iml文件 至此只能临时解决项目运行问题 当修改pom文件或者重新使用maven命令c
  • 【小蓓学AD20】如何修改原理图右下角的标题栏

    第一步 在原理图页面双击边缘 在右边可看到如图1所示界面 图1 取消勾选Title Block 第二步 单击Template 进入如图2所示页面 点击按钮 在下拉框里选择你的模板路径 对图3的弹出框不做修改 单击 确定 图2 图3 完成效果
  • 机器学习--决策树(10)

    一 基本概念 1 1 是什么 分类决策树模型是一种描述对实例进行分类的树形结构 相当于if then结构 决策树由节点和有向边构成 节点有两种 一种是内部节点 表示一个特征或者属性 另一种是叶子节点 表示一个决策结果 1 2 优缺点 优点
  • Fedora的启动方式(命令行启动)

    Linux有6种不同的运行级别 默认的情况下Fedora安装完成后是从X Window启动的 X Window占用系统资源很大 所以对于我们仅仅想使用命令行模式的人来说 界面那么大 耗费资源太多有些浪费 那如何让Fedora从命令行启动而不
  • 卷麻了,00后测试用例写的比我还好,简直无地自容......

    经常看到无论是刚入职场的新人 还是工作了一段时间的老人 都会对编写测试用例感到困扰 例如 如何编写测试用例 作为一个测试新人 刚开始接触测试 对于怎么写测试用例很是头疼 无法接触需求 只能站在用户角度去做测试 但是这样情况会导致不能全方位测
  • parallel scavenge 与parnew 区别:

    Parallel Scavenge收集器是一个新生代收集器 它也是使用复制算法的收集器 又是并行的多线程收集器 看上去和ParNew都一样 那它有什么特别之处呢 Parallel Scavenge收集器的特点是它的关注点与其他收集器不同 C
  • 一款盲盒的交友软件叫什么(微信恋爱脱单交友盲盒小程序制作开发介绍)

    盲盒的交友软件一般叫做叫 盲盒脱单神器 月老交友盲盒或者是叫做一元交友等名称都是运营商自己随便起的 微信恋爱脱单交友盲盒小程序 一般情况是以H5网页的形式进行使用 做成微信小程序的形式需要相关资质 主要功能有 幻灯片 放入盒子 随机匹配 星
  • git clone指定分支拉代码、版本回退、log/reflog对比

    指定分支clone代码 1 git clone 不指定分支 默认就是master git clone http 10 1 1 11 service tmall service git 2 git clone 指定分支 git clone b
  • 【2022/2023年硕士研究生408计算机学科考试大纲原文】+【2009-2021年408统考真题+解析PDF】

    文章目录 2009 2021年408统考真题 解析 PDF版 I 考试性质 II 考查目标 III 试形式和试卷结构 一 试卷满分及考试时间 二 答题方式 三 试卷内容结构 四 试卷题型结构 IV 考查内容 数据结构 一 线性表 二 栈 队
  • CAS 5.3自定义 登录

    自定义认证校验策略 我们知道CAS为我们提供了多种认证数据源 我们可以选择JDBC File JSON等多种方式 但是如果我想在自己的认证方式中可以根据提交的信息实现不同数据源选择 这种方式就需要我们去实现自定义认证 自定义策略主要通过现实