首页 > 其他分享 >【CAS】CAS 多属性返回(五)

【CAS】CAS 多属性返回(五)

时间:2025-01-19 23:22:43浏览次数:1  
标签:返回 jdbc CAS cas authn import 属性

原理

  在 CAS 5.3.2 中,登录成功后返回用户的多个属性内容是通过 Principal 对象实现的。Principal 包含了用户的基本信息(如用户名)以及额外的属性(如邮箱、电话、角色等)。

  具体逻辑其实还是在 AuthenticationHandler 处理的,AuthenticationHandler原理参考(【CAS】CAS 自定义登录验证(四) - H__D - 博客园

数据库验证用户多属性返回

  AI回答如下:

1. 配置数据库认证

首先,配置 CAS 使用数据库进行用户认证。CAS 提供了 QueryDatabaseAuthenticationHandler 用于从数据库中验证用户。

修改 application.properties 或 cas.properties

properties 复制
# 启用数据库认证
cas.authn.jdbc.query[0].sql=SELECT * FROM users WHERE username=?
cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/cas
cas.authn.jdbc.query[0].user=root
cas.authn.jdbc.query[0].password=password
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
cas.authn.jdbc.query[0].fieldPassword=password
cas.authn.jdbc.query[0].fieldExpired=expired
cas.authn.jdbc.query[0].fieldDisabled=disabled
  • sql:查询用户的 SQL 语句。

  • url:数据库连接 URL。

  • user:数据库用户名。

  • password:数据库密码。

  • driverClass:数据库驱动类。

  • fieldPassword:密码字段。

  • fieldExpired:账户是否过期的字段。

  • fieldDisabled:账户是否禁用的字段。


2. 返回用户多属性

在数据库查询中,除了验证用户名和密码,还可以查询用户的多个属性(如邮箱、电话、角色等),并将这些属性返回给 CAS。

修改 SQL 查询

确保 SQL 查询返回用户的多个属性。例如:

sql 复制
SELECT username, password, email, phone, roles FROM users WHERE username=?

配置属性映射

在 application.properties 或 cas.properties 中,配置数据库字段到 CAS 属性的映射:

properties 复制
cas.authn.jdbc.query[0].principalAttributeList=email,phone,roles
cas.authn.jdbc.query[0].attributeMapping.email=email
cas.authn.jdbc.query[0].attributeMapping.phone=phone
cas.authn.jdbc.query[0].attributeMapping.roles=roles
  • principalAttributeList:指定要返回的属性名称。

  • attributeMapping:将数据库字段映射到 CAS 属性。


3. 自定义 Principal 属性

如果默认的 QueryDatabaseAuthenticationHandler 无法满足需求,您可以实现自定义的 AuthenticationHandler,从数据库中查询用户属性并返回。

自定义 AuthenticationHandler 示例

java 复制
package com.example.cas.auth;

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 org.springframework.jdbc.core.JdbcTemplate;

import javax.security.auth.login.FailedLoginException;
import javax.sql.DataSource;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DatabaseAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {

    private final JdbcTemplate jdbcTemplate;

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

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

        String username = credential.getUsername();
        String password = credential.getPassword();

        // 查询用户信息
        String sql = "SELECT username, password, email, phone, roles FROM users WHERE username=?";
        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, username);

        if (result.isEmpty()) {
            throw new FailedLoginException("User not found: " + username);
        }

        Map<String, Object> user = result.get(0);
        String dbPassword = (String) user.get("password");

        // 验证密码
        if (!password.equals(dbPassword)) {
            throw new FailedLoginException("Invalid password for user: " + username);
        }

        // 定义用户属性
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("email", user.get("email"));
        attributes.put("phone", user.get("phone"));
        attributes.put("roles", user.get("roles"));

        // 创建 Principal 对象,包含用户名和属性
        return createHandlerResult(credential, this.principalFactory.createPrincipal(username, attributes));
    }

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

4. 注册自定义 AuthenticationHandler

通过 AuthenticationEventExecutionPlanConfigurer 接口将自定义的 DatabaseAuthenticationHandler 注册到 CAS 的认证流程中。

注册自定义处理器

java 复制
package com.example.cas.config;

import com.example.cas.auth.DatabaseAuthenticationHandler;
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.services.ServicesManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration("databaseAuthenticationConfiguration")
public class DatabaseAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {

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

    @Autowired
    private DataSource dataSource;

    @Bean
    public AuthenticationHandler databaseAuthenticationHandler() {
        return new DatabaseAuthenticationHandler(
            DatabaseAuthenticationHandler.class.getSimpleName(), // 处理器名称
            servicesManager, // ServicesManager
            new DefaultPrincipalFactory(), // PrincipalFactory
            1, // 处理器顺序
            dataSource // 数据源
        );
    }

    @Override
    public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
        // 注册自定义的认证处理器
        plan.registerAuthenticationHandler(databaseAuthenticationHandler());
    }
}

5. 配置 CAS 返回属性

在 application.properties 或 cas.properties 中,启用属性释放功能:

properties 复制
# 启用属性释放
cas.authn.attributeRepository.defaultAttributesToRelease=email,phone,roles

6. 测试登录并获取属性

  1. 启动 CAS 服务

    • 使用以下命令打包并启动 CAS:

      bash 复制
      ./gradlew clean build
      ./gradlew run
  2. 访问 CAS 登录页面

    • 打开浏览器,访问 http://localhost:8080/cas/login

  3. 登录并查看属性

    • 使用数据库中的用户名和密码登录。

    • 登录成功后,CAS 会返回包含用户属性的票据(如 TGT 或 ST)。

    • 在服务端,可以通过 CAS 客户端库解析票据,获取用户属性。


7. 总结

通过以上步骤,您可以在 CAS 登录成功后返回数据库用户的多个属性内容。关键点包括:

  1. 配置数据库认证。

  2. 在 SQL 查询中返回用户属性。

  3. 配置属性映射和释放。

  4. 实现自定义的 AuthenticationHandler(可选)。

  5. 在客户端解析票据,获取用户属性。

这种方法适用于 CAS 5.3.2 及更高版本,能够灵活地从数据库中获取并返回用户属性。

测试验证

  本例测试的是数据库查询用户,并返回属性,具体逻辑在源码的 QueryDatabaseAuthenticationHandler 类中

1、在application.properties配置

# 查询配置
cas.authn.attributeRepository.jdbc[0].dialect=org.hibernate.dialect.MySQLDialect
cas.authn.attributeRepository.jdbc[0].driverClass=com.mysql.cj.jdbc.Driver
cas.authn.attributeRepository.jdbc[0].url=jdbc:mysql://127.0.0.1:3306/cas?characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useSSL=false&rewriteBatchedStatements=true
cas.authn.attributeRepository.jdbc[0].user=root
cas.authn.attributeRepository.jdbc[0].password=123456

# 查询SQL
cas.authn.attributeRepository.jdbc[0].sql=select * from user where {0}
# 以下属性为查询sql时,当为多个时逗号分隔,如填写username、email,sql会变成 select * from user where username=${?} {and/or} email=${?}
cas.authn.attributeRepository.jdbc[0].username=username
cas.authn.attributeRepository.jdbc[0].singleRow=true
cas.authn.attributeRepository.jdbc[0].order=0
cas.authn.attributeRepository.jdbc[0].requireAllAttributes=true
# cas.authn.attributeRepository.jdbc[0].caseCanonicalization=NONE|LOWER|UPPER
# cas.authn.attributeRepository.jdbc[0].queryType=OR|AND

# 单行属性
cas.authn.attributeRepository.jdbc[0].attributes.id=id
cas.authn.attributeRepository.jdbc[0].attributes.username=username
cas.authn.attributeRepository.jdbc[0].attributes.first_name=first_name
cas.authn.attributeRepository.jdbc[0].attributes.last_name=last_name

 

2、启动CAS服务,登录

  登录成功,

  

  点击查询属性,可以看到 id、first_name、last_name、username 均已返回

  

 

 

   

 

标签:返回,jdbc,CAS,cas,authn,import,属性
From: https://www.cnblogs.com/h--d/p/18680488

相关文章

  • oracle使用case when报错ORA-12704字符集不匹配原因分析及解决方法
    问题概述使用oracle的casewhen函数时,报错提示ORA-12704字符集不匹配,如下图,接下来分析报错原因并提出解决方法。样例演示现在有一个TESTTABLE表,本表包含的字段如下图所示,COL01字段是NVARCHAR2类型,COL02字段是VARCHAR2类型。场景一使用case简单函数,case后面的内容和when......
  • 卷积加法自注意力CASAtt详解及代码复现
    自注意力机制简介自注意力机制(Self-Attention)是一种特殊的注意力机制,允许模型在处理序列数据时考虑每个元素与其他所有元素的关系。这种机制通过计算查询、键和值向量,帮助模型更好地理解序列中的上下文信息。自注意力机制的核心在于计算每个元素的权重,反映元素之间的相互关......
  • 在js中函数返回多个值有哪些方法?
    在JavaScript中,函数本身不能直接返回多个值,但可以通过一些技巧和模式来模拟这一行为。以下是一些常见的方法:使用数组:将多个值放入一个数组中,并返回该数组。这是最简单和最常用的方法。functiongetMultipleValues(){return[1,'two',true];}const[value1,value2......
  • 【CAS】CAS 接入配置中心SpringCloud Config(三)
    环境准备准备一个SpringCloud Config配置中心,参考:【SpringCloud】SpringCloudConfig配置中心(二十)-H__D-博客园步骤1、启动Config服务,并在Config服务器中,新增cas-server.properties文件文件内容,我就修改了端口server.context-path=/casserver.port=8442......
  • 【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件
    ......
  • cv(const-volatile)属性的作用
    在C++中,cv是const-volatile的缩写,表示类型的const和volatile修饰符。它们用来修饰变量或对象,影响变量的行为,主要和变量的可修改性和编译器优化相关。C++中cv属性的作用const修饰符表示变量是只读的,不能被修改。如果试图修改const修饰的变量,编译器会报错。例......
  • if-else对比switch-case
    概述在编程中,控制流语句用于控制程序的执行路径。if-else和 switch-case是两种常见的控制流语句,分别适用于不同的场景。了解它们的区别和最佳使用场景,有助于编写更高效、可读性更强的代码。if-else结构1.基本语法if-else语句根据布尔表达式的结果来选择执行不同的代码块。其......
  • #CSS 实用属性总结
    文章目录防脱发神器颜色的Alpha通道尺寸的百分比最大最小宽高伪类选择器`contenteditable`属性`table`元素CSS中的大小/长度单位绝对单位相对单位与字体大小相关与视窗大小相关百分比单位动态计算单位时间单位角度单位分辨率单位使用建议防脱发神器为了更直观......
  • Vue.js组件开发-实现后端返回二进制文件在浏览器自动下载
    在Vue.js组件开发中,若需实现从后端获取二进制文件并触发浏览器自动下载,可以利用axios(或其他HTTP客户端库)来向后端发送请求,随后利用Blob对象及URL.createObjectURL方法生成一个可供下载的链接,最后通过创建一个隐藏的<a>元素或利用window.location来启动下载。步骤‌1.发送请求......
  • 2025-01-17:构成整天的下标对数目Ⅰ。用go语言,给定一个整数数组 hours,其中每个元素表示
    2025-01-17:构成整天的下标对数目Ⅰ。用go语言,给定一个整数数组hours,其中每个元素表示以小时为单位的时间,要求返回一个整数,表示满足条件i<j且hours[i]+hours[j]为24的整数倍的下标对(i,j)的数量。这里,整天被定义为时间持续的时长是24小时的整数倍。例如,1天......