Java:如何使用 UrlConnection 发布具有授权的请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2026260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: how to use UrlConnection to post request with authorization?
提问by Niko Gamulin
I would like to generate POST request to a server which requires authentication. I tried to use the following method:
我想向需要身份验证的服务器生成 POST 请求。我尝试使用以下方法:
private synchronized String CreateNewProductPOST (String urlString, String encodedString, String title, String content, Double price, String tags) {
String data = "product[title]=" + URLEncoder.encode(title) +
"&product[content]=" + URLEncoder.encode(content) +
"&product[price]=" + URLEncoder.encode(price.toString()) +
"&tags=" + tags;
try {
URL url = new URL(urlString);
URLConnection conn;
conn = url.openConnection();
conn.setRequestProperty ("Authorization", "Basic " + encodedString);
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
// Process line...
}
wr.close();
rd.close();
return rd.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
return e.getMessage();
}
catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
}
but the server doesn't receive the authorization data. The line which is supposed to add authorization data is the following:
但服务器没有收到授权数据。应该添加授权数据的行如下:
conn.setRequestProperty ("Authorization", "Basic " + encodedString);
and the line
和线
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
also throws an IOException.
还会抛出 IOException。
Anyway I would be very thankful if anyone could suggest any fix of the logic above in order to enable authorization using POST with UrlConnection.
无论如何,如果有人可以建议对上述逻辑进行任何修复,以便使用带有 UrlConnection 的 POST 启用授权,我将非常感激。
but obviously it doesn't work as it is supposed to although if the same logic is used for GET request everything works fine.
但显然它不能正常工作,尽管如果 GET 请求使用相同的逻辑,一切正常。
采纳答案by Adeel Ansari
A fine example found here. Powerlordgot it right, below, for POST you need HttpURLConnection
, instead.
一个很好的例子在这里找到。Powerlord说得对,下面是您需要的 POST HttpURLConnection
。
Below is the code to do that,
下面是执行此操作的代码,
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setRequestProperty ("Authorization", encodedCredentials);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(data);
writer.flush();
String line;
BufferedReader reader = new BufferedReader(new
InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
writer.close();
reader.close();
Change URLConnection
to HttpURLConnection
, to make it POST request.
更改URLConnection
为HttpURLConnection
, 使其成为 POST 请求。
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
Suggestion (...in comments):
建议(...在评论中):
You might need to set these properties too,
您可能还需要设置这些属性,
conn.setRequestProperty( "Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "Accept", "*/*" );
回答by jarnbjo
HTTP authorization does not differ between GET and POST requests, so I would first assume that something else is wrong. Instead of setting the Authorization header directly, I would suggest using the java.net.Authorization class, but I am not sure if it solves your problem. Perhaps your server is somehow configured to require a different authorization scheme than "basic" for post requests?
HTTP 授权在 GET 和 POST 请求之间没有区别,所以我首先假设其他事情是错误的。我建议使用 java.net.Authorization 类,而不是直接设置 Authorization 标头,但我不确定它是否能解决您的问题。也许您的服务器以某种方式配置为需要与 post 请求的“基本”不同的授权方案?
回答by Oscar
i was looking information about how to do a POST request. I need to specify that mi request is a POST request because, i'm working with RESTful web services that only uses POST methods, and if the request isn't post, when i try to do the request i receive an HTTP error 405. I assure that my code isn't wrong doing the next: I create a method in my web service that is called through GET request and i point my application to consume that web service method and it works. My code is the next:
我正在寻找有关如何执行 POST 请求的信息。我需要指定 mi 请求是 POST 请求,因为我正在使用仅使用 POST 方法的 RESTful Web 服务,如果请求不是 post,当我尝试执行请求时,我会收到 HTTP 错误 405。我保证我的代码在接下来的操作中没有错:我在我的 Web 服务中创建了一个通过 GET 请求调用的方法,并且我指向我的应用程序使用该 Web 服务方法并且它可以工作。我的代码是下一个:
URL server = null;
URLConnection conexion = null;
BufferedReader reader = null;
server = new URL("http://localhost:8089/myApp/resources/webService");
conexion = server.openConnection();
reader = new BufferedReader(new InputStreamReader(server.openStream()));
System.out.println(reader.readLine());
回答by Powerlord
I don't see anywhere in the code where you specify that this is a POST request. Then again, you need a java.net.HttpURLConnection
to do that.
我在代码中没有看到您指定这是 POST 请求的任何地方。再说一次,你需要一个java.net.HttpURLConnection
来做到这一点。
In fact, I highly recommend using HttpURLConnection
instead of URLConnection
, with conn.setRequestMethod("POST");
and see if it still gives you problems.
事实上,我强烈建议使用HttpURLConnection
代替URLConnection
, withconn.setRequestMethod("POST");
并查看它是否仍然给您带来问题。
回答by Dimitris
To send a POST request call:
要发送 POST 请求调用:
connection.setDoOutput(true); // Triggers POST.
If you want to sent text in the request use:
如果要在请求中发送文本,请使用:
java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(connection.getOutputStream());
wr.write(textToSend);
wr.flush();
回答by Harvinder
I ran into this problem today and none of the solutions posted here worked. However, the code posted hereworked for a POSTrequest:
我今天遇到了这个问题,这里发布的解决方案都没有奏效。但是,此处发布的代码适用于POST请求:
// HTTP POST request
private void sendPost() throws Exception {
String url = "https://selfsolve.apple.com/wcResults.do";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
It turns out that it's not the authorization that's the problem. In my case, it was an encoding problem. The content-type I needed was application/jsonbut from the Java documentation:
事实证明,问题不是授权。就我而言,这是一个编码问题。我需要的内容类型是application/json但来自 Java 文档:
static String encode(String s, String enc)
Translates a string into application/x-www-form-urlencoded format using a specific encoding scheme.
The encode function translates the string into application/x-www-form-urlencoded.
encode 函数将字符串转换为application/x-www-form-urlencoded。
Now if you don't set a Content-Type, you may get a 415 Unsupported Media Type error. If you set it to application/jsonor anything that's not application/x-www-form-urlencoded, you get an IOException. To solve this, simply avoid the encode method.
现在,如果您不设置 Content-Type,您可能会收到 415 Unsupported Media Type 错误。如果将其设置为application/json或任何不是application/x-www-form-urlencoded 的内容,则会收到 IOException。要解决这个问题,只需避免使用 encode 方法。
For this particular scenario, the following should work:
对于这种特殊情况,以下应该起作用:
String data = "product[title]=" + title +
"&product[content]=" + content +
"&product[price]=" + price.toString() +
"&tags=" + tags;
Another small piece of information that might be helpful as to why the code breaks when creating the buffered reader is because the POSTrequest actually only gets executed when conn.getInputStream()is called.
关于为什么在创建缓冲读取器时代码中断的原因可能有用的另一小信息是因为POST请求实际上仅在调用 conn.getInputStream()时才会执行。
回答by lejallec
To do oAuth authentication to external app (INSTAGRAM) Step 3 "get the token after receiving the code" Only code below worked for me
对外部应用程序 (INSTAGRAM) 进行 oAuth 身份验证第 3 步“收到代码后获取令牌”只有下面的代码对我有用
Worth to state also that it worked for me using some localhost URL with a callback servlet configured with name "callback in web.xml and callback URL registered: e.g. localhost:8084/MyAPP/docs/insta/callback
值得一提的是,它使用一些本地主机 URL 和回调 servlet 对我有用
BUT after successfully completed authentication steps, using same external site "INSTAGRAM" to do GET of Tags or MEDIA to retrieve JSON data using initial method didn't work. Inside my servlet to do GET using url like e.g. api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN only method found HEREworked
但是在成功完成身份验证步骤后,使用相同的外部站点“INSTAGRAM”来获取标签或媒体以使用初始方法检索 JSON 数据不起作用。在我的 servlet 内使用 url 执行 GET,例如 api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN 仅在此处找到的方法有效
Thanks to all contributors
感谢所有贡献者
URL url = new URL(httpurl);
HashMap<String, String> params = new HashMap<String, String>();
params.put("client_id", id);
params.put("client_secret", secret);
params.put("grant_type", "authorization_code");
params.put("redirect_uri", redirect);
params.put("code", code); // your INSTAGRAM code received
Set set = params.entrySet();
Iterator i = set.iterator();
StringBuilder postData = new StringBuilder();
for (Map.Entry<String, String> param : params.entrySet()) {
if (postData.length() != 0) {
postData.append('&');
}
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("\n");
}
reader.close();
conn.disconnect();
System.out.println("INSTAGRAM token returned: "+builder.toString());
回答by yubaraj poudel
On API 22 The Use Of BasicNamevalue Pair is depricated, instead use the HASMAP for that. To know more about the HasMap visit here more on hasmap developer.android
在 API 22 上,不推荐使用 BasicNamevalue 对,而是为此使用 HASMAP。要了解有关 HasMap 的更多信息,请访问hasmap developer.android
package com.yubraj.sample.datamanager;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import com.yubaraj.sample.utilities.GeneralUtilities;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
/**
* Created by yubraj on 7/30/15.
*/
public class ServerRequestHandler {
private static final String TAG = "Server Request";
OnServerRequestComplete listener;
public ServerRequestHandler (){
}
public void doServerRequest(HashMap<String, String> parameters, String url, int requestType, OnServerRequestComplete listener){
debug("ServerRequest", "server request called, url = " + url);
if(listener != null){
this.listener = listener;
}
try {
new BackgroundDataSync(getPostDataString(parameters), url, requestType).execute();
debug(TAG , " asnyc task called");
} catch (Exception e) {
e.printStackTrace();
}
}
public void doServerRequest(HashMap<String, String> parameters, String url, int requestType){
doServerRequest(parameters, url, requestType, null);
}
public interface OnServerRequestComplete{
void onSucess(Bundle bundle);
void onFailed(int status_code, String mesage, String url);
}
public void setOnServerRequestCompleteListener(OnServerRequestComplete listener){
this.listener = listener;
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
class BackgroundDataSync extends AsyncTask<String, Void , String>{
String params;
String mUrl;
int request_type;
public BackgroundDataSync(String params, String url, int request_type){
this.mUrl = url;
this.params = params;
this.request_type = request_type;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... urls) {
debug(TAG, "in Background, urls = " + urls.length);
HttpURLConnection connection;
debug(TAG, "in Background, url = " + mUrl);
String response = "";
switch (request_type) {
case 1:
try {
connection = iniitializeHTTPConnection(mUrl, "POST");
OutputStream os = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(params);
writer.flush();
writer.close();
os.close();
int responseCode = connection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
/* String line;
BufferedReader br=new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line=br.readLine()) != null) {
response+=line;
}*/
response = getDataFromInputStream(new InputStreamReader(connection.getInputStream()));
} else {
response = "";
}
} catch (IOException e) {
e.printStackTrace();
}
break;
case 0:
connection = iniitializeHTTPConnection(mUrl, "GET");
try {
if (connection.getResponseCode() == connection.HTTP_OK) {
response = getDataFromInputStream(new InputStreamReader(connection.getInputStream()));
}
} catch (Exception e) {
e.printStackTrace();
response = "";
}
break;
}
return response;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(TextUtils.isEmpty(s) || s.length() == 0){
listener.onFailed(DbConstants.NOT_FOUND, "Data not found", mUrl);
}
else{
Bundle bundle = new Bundle();
bundle.putInt(DbConstants.STATUS_CODE, DbConstants.HTTP_OK);
bundle.putString(DbConstants.RESPONSE, s);
bundle.putString(DbConstants.URL, mUrl);
listener.onSucess(bundle);
}
//System.out.println("Data Obtained = " + s);
}
private HttpURLConnection iniitializeHTTPConnection(String url, String requestType) {
try {
debug("ServerRequest", "url = " + url + "requestType = " + requestType);
URL link = new URL(url);
HttpURLConnection conn = (HttpURLConnection) link.openConnection();
conn.setRequestMethod(requestType);
conn.setDoInput(true);
conn.setDoOutput(true);
return conn;
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
}
private String getDataFromInputStream(InputStreamReader reader){
String line;
String response = "";
try {
BufferedReader br = new BufferedReader(reader);
while ((line = br.readLine()) != null) {
response += line;
debug("ServerRequest", "response length = " + response.length());
}
}
catch (Exception e){
e.printStackTrace();
}
return response;
}
private void debug(String tag, String string) {
Log.d(tag, string);
}
}
and Just call the function when you needed to get the data from server either by post or get like this
当您需要通过邮寄或像这样从服务器获取数据时,只需调用该函数
HashMap<String, String>params = new HashMap<String, String>();
params.put("action", "request_sample");
params.put("name", uname);
params.put("message", umsg);
params.put("email", getEmailofUser());
params.put("type", "bio");
dq.doServerRequest(params, "your_url", DbConstants.METHOD_POST);
dq.setOnServerRequestCompleteListener(new ServerRequestHandler.OnServerRequestComplete() {
@Override
public void onSucess(Bundle bundle) {
debug("data", bundle.getString(DbConstants.RESPONSE));
}
@Override
public void onFailed(int status_code, String mesage, String url) {
debug("sample", mesage);
}
});
Now it is complete.Enjoy!!! Comment it if find any problem.
现在完成了。享受!如果发现任何问题,请评论。