修复IAM问题

This commit is contained in:
2026-08-18 22:33:49 +08:00
parent e7ca06736c
commit 8bb18c6f6a
3 changed files with 39 additions and 9 deletions
@@ -26,6 +26,7 @@
package org.springblade.auth.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Data;
import java.util.Map;
@@ -43,6 +44,13 @@ public class IamSsoProfileResponse {
*/
private String id;
/**
* IAM返回的本系统账号,部分部署直接返回在顶层。
*/
@JsonProperty("account_no")
@JsonAlias({"accountNo", "account", "username", "user_name"})
private String accountNo;
/**
* IAM用户扩展属性
*/
@@ -54,12 +62,20 @@ public class IamSsoProfileResponse {
* @return 本系统账号
*/
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getAccountNo() {
if (attributes == null) {
return null;
public String resolveAccountNo() {
if (accountNo != null && !accountNo.isBlank()) {
return accountNo;
}
Object accountNo = attributes.get("account_no");
return accountNo == null ? null : String.valueOf(accountNo);
if (attributes == null) {
return id;
}
for (String key : new String[]{"account_no", "accountNo", "account", "username", "user_name"}) {
Object value = attributes.get(key);
if (value != null && !String.valueOf(value).isBlank()) {
return String.valueOf(value);
}
}
return id;
}
}
@@ -143,7 +143,7 @@ public class IamSsoTokenGranter extends AuthorizationCodeGranter {
}
IamSsoProfileResponse profileResponse = requestIamProfile(accessToken);
String accountNo = profileResponse.getAccountNo();
String accountNo = profileResponse.resolveAccountNo();
if (StringUtil.isBlank(accountNo)) {
log.warn("IAM统一身份认证用户信息缺少account_noiamId={}", profileResponse.getId());
throw new UserInvalidException(OAuth2TokenConstant.USER_NOT_FOUND);
@@ -165,23 +165,32 @@ public class IamSsoTokenGranter extends AuthorizationCodeGranter {
private UserInfo loadOrCreateIamUser(OAuth2Request request, IamSsoProfileResponse profileResponse, String tenantId, String accountNo) {
R<UserInfo> result = userClient.userInfo(tenantId, accountNo);
if (result.isSuccess() && result.getData() != null) {
if (result.isSuccess() && hasUser(result.getData())) {
return result.getData();
}
log.info("IAM统一身份认证未匹配到本系统账号,开始自动创建用户,tenantId={}, accountNo={}", tenantId, accountNo);
log.info("IAM统一身份认证未匹配到本系统账号,开始自动创建用户,tenantId={}, accountNo={}, querySuccess={}",
tenantId, accountNo, result.isSuccess());
R<Boolean> saveResult = userClient.saveIamUser(buildIamUser(profileResponse, tenantId, accountNo));
if (!saveResult.isSuccess() || !Boolean.TRUE.equals(saveResult.getData())) {
log.warn("IAM统一身份认证自动创建用户失败,tenantId={}, accountNo={}, msg={}", tenantId, accountNo, saveResult.getMsg());
throw new UserInvalidException(OAuth2TokenConstant.USER_NOT_FOUND);
}
R<UserInfo> createdResult = userClient.userInfo(tenantId, accountNo);
if (!createdResult.isSuccess() || createdResult.getData() == null) {
if (!createdResult.isSuccess() || !hasUser(createdResult.getData())) {
log.warn("IAM统一身份认证自动创建用户后未查询到用户,tenantId={}, accountNo={}", tenantId, accountNo);
throw new UserInvalidException(OAuth2TokenConstant.USER_NOT_FOUND);
}
return createdResult.getData();
}
/**
* Feign 返回成功时,data 仍可能是一个 user 为空的 UserInfo 包装对象。
* IAM 登录必须确保本地用户实体存在,避免被误报为密码校验失败。
*/
private boolean hasUser(UserInfo userInfo) {
return userInfo != null && userInfo.getUser() != null;
}
private User buildIamUser(IamSsoProfileResponse profileResponse, String tenantId, String accountNo) {
User user = new User();
user.setTenantId(tenantId);
@@ -40,6 +40,7 @@ import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.DesUtil;
import org.springblade.core.tool.utils.SM2Util;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.cache.SysCache;
import org.springblade.system.pojo.entity.Tenant;
@@ -74,6 +75,10 @@ public class BladeAuthorizationHandler extends AbstractAuthorizationHandler {
*/
@Override
public OAuth2Validation preValidation(OAuth2Request request) {
// IAM授权码已经由外部身份系统完成认证,不读取或校验本地密码。
if (StringUtil.equals("iam_sso", request.getGrantType())) {
return new OAuth2Validation();
}
if (request.isPassword() || request.isCaptchaCode()) {
// 生产环境弱密码校验
if (bladeProperties.isProd() && isWeakPassword(request.getPassword())) {