如何在不使用 rest admin api 的情况下以编程方式(java)更新 keycloak 的用户详细信息?

Posted

技术标签:

【中文标题】如何在不使用 rest admin api 的情况下以编程方式(java)更新 keycloak 的用户详细信息?【英文标题】:How can I update keycloak's user details programmatically (java), without using rest admin api? 【发布时间】:2017-11-24 07:34:21 【问题描述】:

我想更新用户详细信息。例如我从 keycloak 管理控制台在“演示”领域创建了用户(k1)。我有一个 java 客户端,我想更新用户(k1)的详细信息。更改用户 k1 的电子邮件地址。

我确实使用了管理客户端(Rest API),如下所示。

public void updateEmail(final String newEmailAddress) 
    try 
        final AccessToken accessToken = getToken();
        Keycloak keycloak = KeycloakBuilder.builder().serverUrl(this.getDeployment().getAuthServerBaseUrl())
                .realm(this.getDeployment().getRealm()).username("k1").password("123").clientId(ADMIN_CLIENT)
                .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();

        UserResource userResource = keycloak.realm(this.getDeployment().getRealm()).users()
                .get(accessToken.getSubject());
        UserRepresentation user = userResource.toRepresentation();
        user.setEmail(newEmailAddress);
        userResource.update(user);

     catch (Exception exception) 
        exception.printStackTrace();
    

但我想在不使用管理客户端的情况下做同样的事情。

【问题讨论】:

没有 REST 客户端怎么办?这是不可能的,或者您使用控制台或 REST 端点... 我正在使用管理员帐户来更新用户的电子邮件。即keycloak 管理客户端。我需要另一种方式。 您是否找到了更多关于让用户在不使用管理员凭据的情况下使用访问令牌更新其信息的推荐方法的信息?我一直在四处寻找,暂时找不到。 这个答案中有两个选项,update-own-profile,用户服务或帐户配置文件主题。 【参考方案1】:

我使用以下方法做到了。

    public void updateEmail(final String newEmailAddress)
        throws ClientProtocolException, IOException, HttpFailure, VerificationException 

    List<NameValuePair> formparams = new ArrayList<>();

    formparams.add(new BasicNameValuePair("stateChecker", "QW1iwts0YS8pC0JDosACq-2ZAJHtTW8HWN7KSgTV8rc"));
    formparams.add(new BasicNameValuePair("email", "5somebody@gmail.com"));
    formparams.add(new BasicNameValuePair("firstName", "1some"));
    formparams.add(new BasicNameValuePair("lastName", "1body"));

    KeycloakDeployment deployment = this.getDeployment();

    HttpPost post = new HttpPost("http://localhost:8080/auth/realms/demo/account/");
    ClientCredentialsProviderUtils.setClientCredentials(deployment, post, formparams);
    post.setHeader("Accept", "application/json");
    post.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    post.setHeader("Authorization", "Bearer " + this.getTokenString(10, TimeUnit.SECONDS));

    UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
    post.setEntity(form);

    HttpResponse response = deployment.getClient().execute(post);

    if (response.getStatusLine().getStatusCode() == 200) 
        print(response.getEntity().getContent());
     else 
        print(response.getEntity().getContent());
        System.out.println(response.getStatusLine().toString());
    

要完成上述操作,我需要更改我的 account.ftl(位于 *:*\keycloak-demo-3.1.0.Final\keycloak\themes\base\ account\account.ftl) 如下

    <#if stateChecker??>
        <input type="hidden" id="stateChecker" name="stateChecker" value="$stateChecker?html">
    <#else>
        <input type="hidden" id="stateChecker" name="stateChecker" value=" ">
    </#if>

更改背后的原因是,我收到如下错误:

无法处理模板:org.keycloak.theme.FreeMarkerException:无法处理模板 account.ftl

【讨论】:

【参考方案2】:

您可以使用 jsoup-1.6.0.jar 来更新任何用户的详细信息,如下所示。

public boolean updateAccountDetails(String name, String value) 

String url= getKeycloakAdapter().getDeployment().getAccountUrl();

Document document = Jsoup.connect(url).get();
if (document != null) 
  String formQuery = String.format("form[action^=%s]", url);
  Elements form = document.select(formQuery);
  if (!form.isEmpty()) 
    Elements inputs = form.select("input[value], input:not([disabled])");
    Element saveAction = form.select("button[value=Save]").first();
    inputs.add(saveAction);
    Map<String, String> mandatoryArguments = new HashMap<>();
    for (Element input : inputs) 
      mandatoryArguments.put(input.attr("name"), input.attr("value"));
    
    mandatoryArguments.put(attributeName, newValue);
    Response response = Jsoup.connect(accountUrl)
        .data(mandatoryArguments)
        .method(Method.POST)
        .execute();

    Document finalDoc = response.parse();
    if (finalDoc != null) 
      Elements finalForm = finalDoc.select(formQuery);
      if (finalForm != null) 
        String newValueQuery = String.format("input[name=%s], input[value=%s]", name, value);
        Elements finalInputs = finalForm.select(newValueQuery);
        if (finalInputs != null) 
          return !finalInputs.isEmpty();
        
      
    
  

throw new IOException("Account page not found");

【讨论】:

以上是关于如何在不使用 rest admin api 的情况下以编程方式(java)更新 keycloak 的用户详细信息?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不登录 jwt django rest-framework 的情况下获取请求数据

在不重新发明***的情况下保护 REST API

如何在不使用 PHP 将文件写入磁盘的情况下将文件发布到 REST 服务器?

在不使用 Azure SDK 的情况下使用 REST API 将流上传到 Azure Blob 存储

如何使用 Admin Rest API 将成员添加到 whatsapp 等多用户聊天订阅

有没有办法在不轮询 REST API 的情况下通知 Google AI Platform 训练作业的状态变化?