我想在Key斗篷中保留一些信息作为自定义用户属性。
其中一些应该由用户自己管理。其他属性应仅由Keycloft管理员管理。管理员管理的属性应该是只读的,在用户的"编辑帐户"网页中可见。
我浏览了在该页面中添加自定义用户属性的指南,并自定义了"编辑帐户"网页。
我的问题是:是否确保用户不能更改对用户来说是只读的属性?例如,通过提交一个表单,他/她发送正确的数据,这些数据将在服务器端自动映射到用户属性。
对于您所说的内容,您似乎有三个选择。
其中一个是保留密钥斗篷"编辑帐户"页面,并使用更新配置文件侦听器来检查存储了哪些属性或由谁更新了哪些属性,类似于以下内容:
public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory, DisplayTypeRequiredActionFactory {
@Override
public InitiatedActionSupport initiatedActionSupport() {
return InitiatedActionSupport.SUPPORTED;
}
@Override
public void evaluateTriggers(RequiredActionContext context) {
}
@Override
public void requiredActionChallenge(RequiredActionContext context) {
Response challenge = context.form()
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
}
// Check the custom attribute 1 not being modified by the user
@Override
public void processAction(RequiredActionContext context) {
EventBuilder event = context.getEvent();
event.event(EventType.UPDATE_PROFILE);
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}
@Override
public void close() {
}
@Override
public RequiredActionProvider create(KeycloakSession session) {
return this;
}
@Override
public RequiredActionProvider createDisplay(KeycloakSession session, String displayType) {
if (displayType == null) return this;
if (!OAuth2Constants.DISPLAY_CONSOLE.equalsIgnoreCase(displayType)) return null;
return ConsoleUpdateProfile.SINGLETON;
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public String getDisplayText() {
return "Update Profile";
}
@Override
public String getId() {
return UserModel.RequiredAction.UPDATE_PROFILE.name();
}
}
我不知道的是,当你从客户端应用程序更新配置文件时,这个监听器是否也会被调用。如果它被调用,你需要检查哪个是登录的客户端,如果是公共客户端,不要更新属性,如果是你的服务客户端,让它更新。
第二个将只允许您的服务客户端更新用户配置文件,并在您的应用程序中创建自定义视图,该视图将表单POST发送到您的客户端,而不是直接发送到密钥斗篷。通过这种方式,您可以在将其发送到密钥斗篷之前在服务中对其进行验证。
第三个是实现FormAction
接口,它允许您在服务器端验证传入表单:
必须实现的核心接口是FormAction接口。FormAction负责呈现和处理页面的一部分。渲染在buildPage((方法中完成,验证在validate((方法完成,验证后操作在success((中完成。
@Override
public void validate(ValidationContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}
执行12.0.4版本的更新。存在一些问题<12.0.4,如果用户更新了他的个人资料,将删除所有属性。
此外,使用12.0.4,您可以创建用户和管理员只读属性。
检查文档:https://www.keycloak.org/docs/latest/server_admin/#_read_only_user_attributes
干杯