首页 > 解决方案 > 带有 HttpURLConnection 的 PostRequest 的 401

问题描述

更新 我的问题原来是由于一些超类的怪异。但是,此示例中的 urlEncode 是错误的。在这种情况下,它也是不必要的。如果需要,应该通过每个键和值来完成,而不需要编码 & 或 =。除此之外,此代码是正确的。


下面的(scala)代码失败,因为服务器似乎没有收到正文。服务器日志上的警告是:

警告 *** OAuthTokenProcessor 捕获了带有消息 OAuthProblemException{error='invalid_request', description='Missing grant_type parameter value', uri='null', state='null', scope='null', redirectUri='null' 的 OAuthRequestProblemException ,响应状态=0,参数={}}

我确信参数是正确的。url 正确,标题正确(此调用已在 Postman 和 Python 中有效)

任何提示都非常感谢!

private def doPostRequest(): Unit ={
  try {

    val connectionforPost = (new URL(url)).openConnection.asInstanceOf[HttpURLConnection]


    val params = "grant_type=password&client_id=xxxx&client_secret=seccret&username=admin&password=xxxx"
    val encodedString = URLEncoder.encode(params,"UTF-8")
    import java.nio.charset.StandardCharsets
    val postData = encodedString.getBytes(StandardCharsets.UTF_8)

    val contentlength = Integer.toString(encodedString.length)

    connectionforPost.setConnectTimeout(50000)
    connectionforPost.setReadTimeout(50000)
    connectionforPost.setRequestMethod("POST")
    connectionforPost.setDoOutput(true)
    connectionforPost.setDoInput(true)
    connectionforPost.setInstanceFollowRedirects(false)
    connectionforPost.setRequestProperty("User-agent", "test bot")
    connectionforPost.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
    connectionforPost.setRequestProperty("Accept", "*/*")
    connectionforPost.setRequestProperty("Connection", "keep-alive")
    connectionforPost.setRequestProperty("Content-Length", contentlength)
    connectionforPost.setRequestProperty("Accept-Encoding", "gzip, deflate")
    connectionforPost.setUseCaches(false)


    import java.io.DataOutputStream

    val wr = new DataOutputStream(connectionforPost.getOutputStream)
    wr.write(postData)
    if (wr != null) wr.close()



  } catch{
    case e:Exception => logger.error(e.getMessage,e)
      throw e
  }
}

标签: javascalahttpurlconnection

解决方案


似乎服务器抱怨您没有登录。您收到身份验证问题异常。它通常的工作方式是您向服务器发送请求以使用用户名和密码登录。如果服务器对您进行身份验证(将您的用户名和密码识别为有效的),它会向您发送一个响应,其中包含标头中的身份验证令牌。您可能会在成功登录的响应中看到这 2 个标题:

 access-control-expose-headers=[Authorization], Authorization=[Bearer ....]

这意味着在您的所有后续请求中,您将需要添加一个标头“授权”,该标头将包含值“Bearer ....”。然后服务器会将此请求识别为来自经过身份验证的用户。另外,我建议您可以使用 3d 方 HTTP 客户端。一些著名的客户端是Appache HTTP 客户端OK HTTP 客户端。我使用自己编写的 Http 客户端。它也可作为 MgntUtils 开源库的一部分使用。这是Maven 工件的链接,它也可以在Github上找到,带有源代码和 JavaDoc。这是HttpClient的 javadoc 页面。以下是有关如何获取和使用令牌的代码示例:

        try {
        HttpClient loginClient = new HttpClient();
        loginClient.setConnectionUrl("http://your_url/login");
        loginClient.setRequestProperty("accept", "application/json;charset=UTF-8");
        loginClient.setContentType("application/json");
        String result = loginClient.sendHttpRequest(HttpMethod.POST, "{ \"username\": \"your_user_name\", \"password\": \"Your_password\"}");
        System.out.println(result);
        System.out.println("HTTP " + loginClient.getLastResponseCode() + " " + loginClient.getLastResponseMessage());
        System.out.println("Response headers: " + loginClient.getLastResponseHeaders());
        String accessControlExposeHeader = loginClient.getLastResponseHeader("access-control-expose-headers").get(0);
        String accessKey = loginClient.getLastResponseHeader(accessControlExposeHeader).get(0);
        HttpClient workingClient = new HttpClient();
        workingClient.setRequestProperty("accept", "application/json;charset=UTF-8");
        workingClient.setContentType("application/json");
        workingClient.setRequestProperty(accessControlExposeHeader, accessKey);
        workingClient.setConnectionUrl("http://yourUrl/yourPath");
        System.out.println(workingClient.sendHttpRequest(HttpMethod.GET));
    } catch (IOException e) {
        System.out.println(TextUtils.getStacktrace(e));
    }

推荐阅读