Java:如何使用 UrlConnection 发布授权请求?

Posted

技术标签:

【中文标题】Java:如何使用 UrlConnection 发布授权请求?【英文标题】:Java: how to use UrlConnection to post request with authorization? 【发布时间】:2011-01-02 19:58:54 【问题描述】:

我想向需要身份验证的服务器生成 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();
     

但服务器没有收到授权数据。应该添加授权数据的行如下:

conn.setRequestProperty ("Authorization", "Basic " + encodedString);

和线

BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

还会引发 IOException。

无论如何,如果有人可以建议对上述逻辑进行任何修复,以便使用带有 UrlConnection 的 POST 启用授权,我将非常感激。

但显然它不能按预期工作,尽管如果对 GET 请求使用相同的逻辑,一切正常。

【问题讨论】:

【参考方案1】:

很好example found here。 Powerlord 说得对,below,对于 POST,你需要 HttpURLConnection,而不是。

以下是执行此操作的代码,

    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();

URLConnection 更改为HttpURLConnection,使其发出POST 请求。

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");

建议(...以 cmets 为单位):

您可能还需要设置这些属性,

conn.setRequestProperty( "Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "Accept", "*/*" );

【讨论】:

这是 GET 请求,没有问题。 在授权方面差别不大。 如果你来这里是为了寻找如何做post bit :( 这个答案不正确:这个答案是:***.com/a/2165000/787202 @Stallman:与原始问题中的含义相同。你会找到encodedString 而不是encodedCredential,这意味着密码,简单地说。【参考方案2】:

我在代码中没有看到您指定这是一个 POST 请求的任何地方。再说一次,你需要一个java.net.HttpURLConnection 来做到这一点。

事实上,我强烈建议使用HttpURLConnection 而不是URLConnection,与conn.setRequestMethod("POST"); 一起使用,看看它是否仍然会给您带来问题。

【讨论】:

这是正确答案。您不能使用 URLConnection 发出 post 请求。您必须使用 HttpURLConnection。【参考方案3】:

对外部应用程序(INSTAGRAM)进行 oAuth 身份验证第 3 步“收到代码后获取令牌”只有下面的代码对我有用

还值得一提的是,它对我使用了一些带有回调 servlet 的 localhost URL,其名称为“web.xml 中的回调并注册了回调 URL:例如 localhost:8084/MyAPP/docs/insta/callback”

但在成功完成身份验证步骤后,使用相同的外部站点“INSTAGRAM”执行标签的 GET 或 MEDIA 以使用初始方法检索 JSON 数据不起作用。 在我的 servlet 中使用 url 来做 GET 例如api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN 唯一方法找到HERE 工作

感谢所有贡献者

        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());

【讨论】:

【参考方案4】:

发送 POST 请求调用:

        connection.setDoOutput(true); // Triggers POST.

如果您想在请求中发送文本,请使用:

        java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(connection.getOutputStream());
        wr.write(textToSend);
        wr.flush();

【讨论】:

不。 connection.setDoOutput(true); 不触发 POST。添加此行System.out.println(((HttpURLConnection)connection).getRequestMethod());,您将阅读GET【参考方案5】:

我今天遇到了这个问题,这里发布的解决方案都没有奏效。但是,here 发布的代码适用于 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());


事实证明,问题不在于授权。就我而言,这是一个编码问题。我需要的内容类型是 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.

encode 函数将字符串翻译成application/x-www-form-urlencoded

现在,如果您不设置 Content-Type,您可能会收到 415 Unsupported Media Type 错误。如果你将它设置为 application/json 或任何不是 application/x-www-form-urlencoded 的东西,你会得到一个 IOException。要解决这个问题,只需避免使用 encode 方法。

对于这种特殊情况,以下应该有效:

String data = "product[title]=" + title +
                "&product[content]=" + content + 
                "&product[price]=" + price.toString() +
                "&tags=" + tags;

另一个可能有助于解释为什么在创建缓冲阅读器时代码会中断的小信息是因为 POST 请求实际上只在 conn.getInputStream() 时执行strong> 被调用。

【讨论】:

【参考方案6】:

在 API 22 上,BasicNamevalue 对的使用已被弃用,而是使用 HASMAP。要了解有关 HasMap 的更多信息,请访问此处more on 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);
    

当您需要从服务器获取数据时,只需调用该函数,无论是通过邮寄方式还是像这样获取数据

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);

                        
                    );

现在已经完成了。享受吧!!!发现问题可以评论。

【讨论】:

【参考方案7】:

HTTP 授权在 GET 和 POST 请求之间没有区别,所以我首先假设有其他问题。我建议不要直接设置 Authorization 标头,而是使用 java.net.Authorization 类,但我不确定它是否能解决您的问题。也许您的服务器以某种方式配置为需要不同于“基本”发布请求的授权方案?

【讨论】:

漂亮,我从来不知道这门课。然而,这个类是抽象的,所以他实际上需要一个实现类。 当然,您需要实现特定于应用程序的方式来获取凭据。在交互式应用程序中,您可以例如需要一个弹出对话框。【参考方案8】:

我正在寻找有关如何执行 POST 请求的信息。我需要指定 mi 请求是 POST 请求,因为我正在使用仅使用 POST 方法的 RESTful Web 服务,如果请求未发布,当我尝试执行请求时,我会收到 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());

【讨论】:

以上是关于Java:如何使用 UrlConnection 发布授权请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 java.net.URLConnection 上指定本地地址?

java中的URLConnection如何重用池中的连接

java怎么发http请求

java 如何发送短信

UrlConnection 没有内容类型

URLConnection-URL连接