首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 11 HttpClient -缺少表单参数: grant_type

Java 11 HttpClient -缺少表单参数: grant_type
EN

Stack Overflow用户
提问于 2020-09-17 16:24:53
回答 2查看 1.1K关注 0票数 1

我试图通过Java11的HttpClient从Keycloack服务器获取访问令牌,但一直收到错误:

代码语言:javascript
复制
{
    "error":"invalid_request",
    "error_description":"Missing form parameter: grant_type"
}

顺便说一下,有了邮递员,我就可以拿到代币了。我在我的代码中做的是:

代码语言:javascript
复制
        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不起作用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-17 20:48:28

这就是我们登录的方式:

代码语言:javascript
复制
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;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-11-12 00:53:09

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

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

代码语言:javascript
复制
String requestBody = "username=" + username + "password=" + password + "grant_type=password"

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

代码语言:javascript
复制
HttpRequest request=HttpRequest.newBuilder()
    ...
    .setHeader("content-type", "application/json")
    ...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63934095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档