【问题标题】:Java 11 HttpClient - Missing form parameter: grant_typeJava 11 HttpClient - 缺少表单参数:grant_type
【发布时间】:2021-01-04 02:44:52
【问题描述】:

我正在尝试通过 Java 11 的 HttpClient 从 Keycloack 服务器获取访问令牌。但我不断收到错误消息:

{
    "error":"invalid_request",
    "error_description":"Missing form parameter: grant_type"
}

顺便说一句,用邮递员,我可以得到令牌。我在我的代码中所做的是:

        Map<String, String> values = new HashMap<>() {{
            put("username", username);
            put ("password", password);
            put("grant_type", "password");
        }};

        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writerWithDefaultPrettyPrinter()
                .writeValueAsString(values);

        HttpRequest request=HttpRequest.newBuilder()
                .uri(URI.create(tokenEndpoint))
                .setHeader("client_id", clientId)
                .setHeader("client_secret", clientSecret)
                .setHeader("content-type", "application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();



        HttpClient.newHttpClient()
                .sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body)
                .thenAccept(System.out::println);

        /*
        //Tried also
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
        */

我做错了什么或错过了什么?

Keycloak Missing form parameter: grant_type 无效。

【问题讨论】:

    标签: passwords httpclient keycloak java-11


    【解决方案1】:

    .setHeader("content-type", "application/x-www-form-urlencoded") 行,请求需要表单数据, 但是您在请求正文中发送 json(通过 ObjectMapper.writeValueAsString())。

    如果您尝试发送表单数据,那么这应该是正确的编码:

    String requestBody = "username=" + username + "password=" + password + "grant_type=password"
    

    如果 API 需要 JSON,则将内容类型标头更改为 application/json

    HttpRequest request=HttpRequest.newBuilder()
        ...
        .setHeader("content-type", "application/json")
        ...
    

    【讨论】:

      【解决方案2】:

      这就是我们完成登录的方式:

      MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
      requestParams.add("client_id", keycloakProperties.getResource());
      requestParams.add("username", username);
      requestParams.add("password", password);
      requestParams.add("grant_type", "password");
      requestParams.add("client_secret", String.valueOf(keycloakProperties.getCredentials().get("secret")));
      requestParams.add("scope", "openid");
      
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
      
      HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestParams, headers);
      
      String url = keycloakProperties.getAuthServerUrl() + "/realms/" + keycloakProperties.getRealm() + "/protocol/openid-connect/token";
      
      AccessTokenResponse keycloakAccessToken = getAccessTokenResponse(request, url);
      
      
      // sometimes SSL handshake was failing, so catching error and trying again :)
      private AccessTokenResponse getAccessTokenResponse(HttpEntity<MultiValueMap<String, String>> request, String url) {
          try {
              ResponseEntity<AccessTokenResponse> response = restTemplate.postForEntity(url, request, AccessTokenResponse.class);
              return response.getBody();
          } catch (ResourceAccessException e) {
              log.error("KeyCloak getAccessTokenResponse: " + e.getMessage());
              try {
                  ResponseEntity<AccessTokenResponse> response = restTemplate.postForEntity(url, request, AccessTokenResponse.class);
                  return response.getBody();
              } catch (Exception ex) {
                  throw ex;
              }
          } catch (Exception e) {
              throw e;
          }
      }
      

      【讨论】:

      • 感谢您的回复。我接受你的解决方案,因为它有效。但我想了解为什么我的代码不起作用?我的代码没有什么复杂的。我尝试通过将grant_type 添加到标题、正文、它们两者,没有它,没有任何效果,错误是一样的。我不明白这是什么问题。
      猜你喜欢
      • 2019-05-16
      • 1970-01-01
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 2014-10-14
      • 2019-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多