keycloak~AbstractJsonUserAttributeMapper的(de)作用
AbstractJsonUserAttributeMapper
它是一(yi)個(ge)(ge)抽(chou)象(xiang)類,用(yong)來(lai)更新條件更新用(yong)戶屬性(user_attribute)的(de)信息,我(wo)們在實現自己的(de)mapper時(shi),需要關(guan)注3個(ge)(ge)方法,下(xia)面分別介紹一(yi)下(xia):
getCompatibleProviders方法
它用(yong)來直指(zhi)你的mapper是綁定到哪個認證服務下面的,即這個mapper支持的provider,例如(ru)你想在(zai)微信登錄后(hou)執行這個mapper,你就把微信的provider.id寫到這個方法里(li)返回它即可(ke)
create方法
這個(ge)比較簡單,主要(yao)用來(lai)返回當前mapper的實例(li)對象
updateBrokeredUser方法
這(zhe)是屬性(xing)綁(bang)定的核(he)心方(fang)法,用(yong)來解析第三方(fang)返回的json數據與你(ni)用(yong)戶屬性(xing)和用(yong)戶實體里的字段的對應關系(xi),你(ni)可以理解為字段映射的過程(cheng)
實例
- 更新已綁定過的用戶的firstName和屬性表里的wechat-unionId字段
public class CustomUserAttributeMapper extends AbstractJsonUserAttributeMapper {
public static final String PROVIDER_ID = "custom-user-attribute-mapper";
private static final String[] cp = new String[]{WeiXinIdentityProviderFactory.PROVIDER_ID};
private static final Logger logger = Logger.getLogger(CustomUserAttributeMapper.class);
@Override
public String[] getCompatibleProviders() {
return cp;
}
@Override
public String getId() {
return PROVIDER_ID;
}
// 更新已經綁定過的老用戶的屬性
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
user.setFirstName(context.getFirstName());
// 擴展屬性
user.setSingleAttribute("wechat-unionId", context.getBrokerUserId());
}
@Override
public CustomUserAttributeMapper create(KeycloakSession session) {
logger.info("CustomUserAttributeMapper.create");
return new CustomUserAttributeMapper();
}
}
- 注冊這個mapper到SPI容器
# resources/META-INFO/services/org.keycloak.broker.provider.IdentityProviderMapper文件
org.keycloak.broker.provider.IdentityProviderMapper
- 微信掃碼之后,我們可以看到用戶屬性已經加上了

AbstractJsonUserAttributeMapper的好處
- 不需要修改第三方登錄的核心邏輯
- 符合OCP原則,對擴展開放
- 符合SRP原則,一個類只做一件事
不使用AbstractJsonUserAttributeMapper
- 代碼耦合到AbstractOAuth2IdentityProvider類里,重寫它的updateBrokeredUser方法,它只會更新已綁定過的老用戶的信息。
@Override
public void updateBrokeredUser(
KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
// 擴展屬性
user.setSingleAttribute("unionId", context.getBrokerUserId());
user.setSingleAttribute("latestTime", LocalDateTime.now().toString());
}
