自定义认证校验策略
我们知道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

CAS 5.3自定义 登录相关推荐

  1. Jeesite单点登录集成Cas另加自定义登录验证

    Jeesite单点登录集成Cas另加自定义登录验证 JeeSite是基于多个优秀的开源项目,高度整合封装而成的高效,高性能,强安全性的 开源 Java EE快速开发平台. Cas主要是用来解决多应用之 ...

  2. 修改cas5成功html文件,手把手教Apereo CAS5.2.3 Server端 增量开发 自定义登录页,增加验证码,注册,修改密码等功能的方式...

    很高兴CAS系列帮助到了不少小伙伴,有不少小伙伴加QQ跟我交流 有个比较普遍的问题是大家不知道怎么把注册,修改密码等相关的功能嵌入CAS,这篇博客统一解答下,有些关于spring的内容是我查找资料结合 ...

  3. CAS+SSO配置单点登录完整案例

    CAS+SSO配置单点登录完整案例 目录 CAS+SSO配置单点登录完整案例 部署环境 环境说明 安全证书配置 1.打开cmd命令窗口(管理员身份打开) 2.生成证书,在cmd窗口输入以下命令: 3. ...

  4. FineReport中如何自定义登录界面

    在登录平台时,不希望使用FR默认的内置登录界面,想通过自定义登录界面实现登录操作,内置登录界面如下图: 登录界面,获取到用户名和密码的值,发送到报表系统,报表服务带着这两个参数访问认证地址进行认证. ...

  5. 学习CAS实现SSO单点登录

    学习CAS实现SSO单点登录 网上找了几篇比较详细的教程,在这记录一下: 原理: CAS实现SSO单点登录原理 教程: 1.CAS实现单点登录(SSO)经典完整教程 2.SSO之CAS单点登录实例演示 ...

  6. SharePoint2013自定义登录页面

    SharePoint默认创建的WebApplication是基于windows的身份验证模式,以弹出窗口方式进行身份输入登录.这种方式可能对于国内的企业用户来说感觉不是很友好.一般而言,我们会把这种登 ...

  7. 自定义request_Spring Security 自定义登录认证(二)

    一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...

  8. Spring Security 入门(3-11)Spring Security 的使用-自定义登录验证和回调地址

    配置文件 security-ns.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  9. springboot整合shiro和session的详细过程和自定义登录拦截器

    文章目录 1.shiro依赖 2.shiro配置 shiro过滤器配置: 关联自定义的其他管理器 自定义会话工厂: 3.登陆时记录用户信息 4.shiro一些工具类的学习 5.自定义登录拦截器 shi ...

最新文章

  1. 配置Android环境
  2. 使用脚本编写 Vim 编辑器,第 2 部分: 用户定义函数
  3. CV:基于face库利用cv2调用摄像头(或视频)根据人脸图片实现找人(先指定要识别已知人脸的文件夹转为numpy_array+输入新图片遍历已有numpy_array)
  4. 全面解读java虚拟机
  5. 百度AI加速器三期结业成员企业估值翻2倍 四期启动
  6. python中文人名识别(使用hanlp,LTP,LAC)
  7. keras embedding层_初识TextCNN及keras实现
  8. [转]awsome-python
  9. HDU 6312.Game-博弈-签到题 (2018 Multi-University Training Contest 2 1004)
  10. cad2012打开后闪退_【电脑安装好cad一打开闪退】cad安装完打开闪退_cad2012打开闪退...
  11. 英语好文22.6.23
  12. 精通使用K米短信教程
  13. python 判断完全平方数
  14. 只谈链不谈币,区块链会发展成什么样的方向?
  15. 数字化转型的行业分工和机会分析
  16. NYOJ 779 兰州烧饼
  17. python中的汉字编码(转载,已经注明转载地址)
  18. 使用webStorm创建一个vue项目
  19. 计算机毕业设计之java+ssm的鲜活农产品销售系统
  20. 面了个 4 年 经验的,一问三不知还自认为很牛逼,真是醉了。。

热门文章

  1. window 启动tomcat闪退 查看日志方法
  2. linux 磁盘加密
  3. 销售人员怎么精准的找到自己的产品客户
  4. 北京、深圳、上海三处IT
  5. 5分钟商学院-个人篇-演讲能力
  6. MindManager职场攻略“赶走瞌睡虫”!
  7. AIGC时代,大模型微调如何发挥最大作用?
  8. Verilog设计—简易LED数字时钟
  9. autojs通知栏_基于Auto.js的蚂蚁森林智能脚本 (长期维护) (JavaScript语言)
  10. PHP中的URL加密解密加密