原理
在 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 属性的映射:
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
中,启用属性释放功能:
# 启用属性释放 cas.authn.attributeRepository.defaultAttributesToRelease=email,phone,roles
6. 测试登录并获取属性
-
启动 CAS 服务:
-
使用以下命令打包并启动 CAS:
bash 复制./gradlew clean build ./gradlew run
-
-
访问 CAS 登录页面:
-
打开浏览器,访问
http://localhost:8080/cas/login
。
-
-
登录并查看属性:
-
使用数据库中的用户名和密码登录。
-
登录成功后,CAS 会返回包含用户属性的票据(如 TGT 或 ST)。
-
在服务端,可以通过 CAS 客户端库解析票据,获取用户属性。
-
7. 总结
通过以上步骤,您可以在 CAS 登录成功后返回数据库用户的多个属性内容。关键点包括:
-
配置数据库认证。
-
在 SQL 查询中返回用户属性。
-
配置属性映射和释放。
-
实现自定义的
AuthenticationHandler
(可选)。 -
在客户端解析票据,获取用户属性。
这种方法适用于 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