【问题标题】:HttpUrlConnection Bad RequestHttpUrlConnection 错误请求
【发布时间】:2021-07-08 19:10:23
【问题描述】:

我正在尝试使用 HttpUrlConnection 发送 POST。一切似乎都很好,但它一直返回 400,就好像参数没有在 DataOutputStream 中发送,或者以错误的方式发送。

public String doDBAuth(String dbURL, String dbUser, String dbPassword) throws IOException {
    HttpURLConnection connection = null;

    String res = null;

    try {
        BufferedReader reader;
        StringBuffer buffer;

        URL url = new URL(dbURL + "/auth");
        connection = (HttpURLConnection) url.openConnection();          
        String urlParameters  = "username=actn-admin&password=Test@&cliend_id=admin-cli&grant_type=password";
        byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8 );
        int postDataLength = postData.length;



        connection.setRequestMethod("POST");
        connection.setReadTimeout(40000);
        connection.setConnectTimeout(40000);
        connection.setDoOutput(true);   
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");     
        connection.setRequestProperty("Content-Length", Integer.toString(postDataLength));
        connection.setDoInput(true);


        try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
            wr.writeBytes(urlParameters);
            wr.flush();
        }


        int responseCode = connection.getResponseCode();

        int status = connection.getResponseCode();
        InputStream inputStream;
        if (status == HttpURLConnection.HTTP_OK) {
            inputStream = connection.getInputStream();
        } else {
            inputStream = connection.getErrorStream();
        }
        reader = new BufferedReader(new InputStreamReader(inputStream));
        buffer = new StringBuffer();
        String line = "";
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        res = buffer.toString();

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (ProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }   
    return res;
}  

这是返回的内容:

{"error":"unauthorized_client","error_description":"INVALID_CREDENTIALS: Invalid client credentials"}

这很奇怪,因为这个 curl 可以正常工作:

curl --location --request POST '<URL>/auth' \
> --header 'Content-Type: application/x-www-form-urlencoded' \
> --data-urlencode 'username=actn-admin' \
> --data-urlencode 'password=Test@' \
> --data-urlencode 'client_id=admin-cli' \
> --data-urlencode 'grant_type=password' -k

它会返回我期望的访问令牌

【问题讨论】:

    标签: java rest post httpurlconnection


    【解决方案1】:

    键和值需要进行 URL 编码(here 的规范)。 在您的示例中,将“Test@”替换为“Test%40”就足够了。对于面向未来的解决方案,您应该对所有键和值进行编码(例如使用URLEncoder

    【讨论】:

    • 我添加了String stringToReverse = URLEncoder.encode(urlParameters, "UTF-8");,但没有解决。现在我有这个错误:{"error":"invalid_request","error_description":"Missing form parameter: grant_type"} 我想现在错误在 Content-Type 中,我应该如何计算它,使用参数还是编码的?如果我没有设置 Content-Type 从邮递员那里返回无效授权类型的相同错误
    • @LucaP 请注意,如果您的用户名/密码将来包含任何非 ASCII 字符,您将再次收到 400。为避免这种情况,请直接将 postData 数组写入输出流,而不是使用 writeBytes,后者不适用于非 ASCII 字符。
    • @LucaP 你不能编码 = 字符,只有键和值
    • 请参阅此答案中的第二个示例:stackoverflow.com/a/40576153/13510562
    • 你说得对,我正在编码整个身体。现已修复,它正在工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多