原理
在 CAS 5.3.2 中,登录成功后返回用户的多个属性内容是通过 Principal
对象实现的。Principal
包含了用户的基本信息(如用户名)以及额外的属性(如邮箱、电话、角色等)。
具体逻辑其实还是在 AuthenticationHandler
处理的,AuthenticationHandler原理参考(【CAS】CAS 自定义登录验证(四) - H__D - 博客园)
数据库验证用户多属性返回
AI回答如下:
1. 配置数据库认证
首先,配置 CAS 使用数据库进行用户认证。CAS 提供了 QueryDatabaseAuthenticationHandler
用于从数据库中验证用户。
修改 application.properties
或 cas.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 查询返回用户的多个属性。例如:
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
示例
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