Java: come utilizzare UrlConnection per inviare richiesta con autorizzazione?


Vorrei generare una richiesta POST su un server che richiede l'autenticazione. Ho provato ad usare il seguente metodo:

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

Ma il server non riceve i dati di autorizzazione. La riga che dovrebbe aggiungere i dati di autorizzazione è la seguente:

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

E la riga

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

Genera anche una IOException.

Ad ogni modo sarei molto grato se qualcuno potesse suggerire una correzione della logica sopra per abilitare l'autorizzazione usando PUBBLICA con UrlConnection.

Ma ovviamente non funziona come dovrebbe, anche se se viene utilizzata la stessa logica per la richiesta GET, tutto funziona bene.

Author: Adeel Ansari, 2010-01-08

8 answers

Un buon esempio trovato qui. Powerlord ha capito bene, sotto, per il POST che ti serve HttpURLConnection, invece.

Di seguito è riportato il codice per farlo,

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

Cambia URLConnection in HttpURLConnection, per farlo POSTARE richiesta.

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

Suggerimento (in nei commenti):

Potrebbe essere necessario impostare anche queste proprietà,

conn.setRequestProperty( "Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "Accept", "*/*" );
 47
Author: Adeel Ansari, 2017-05-23 12:18:17

Non vedo da nessuna parte nel codice in cui si specifica che si tratta di una richiesta POST. Poi di nuovo, avete bisogno di un java.net.HttpURLConnection per farlo.

In effetti, consiglio vivamente di usare HttpURLConnection invece di URLConnection, con conn.setRequestMethod("POST"); e vedere se ti dà ancora problemi.

 13
Author: Powerlord, 2010-01-29 20:39:19

Per eseguire l'autenticazione OAuth su app esterna (INSTAGRAM) Passo 3 "ottieni il token dopo aver ricevuto il codice" Solo il codice qui sotto ha funzionato per me

Vale la pena affermare anche che ha funzionato per me usando qualche URL localhost con un servlet di callback configurato con nome "callback in web.URL xml e callback registrati: ad esempio localhost: 8084 / MyAPP / docs/insta / callback

MA dopo aver completato con successo i passaggi di autenticazione, utilizzando lo stesso sito esterno "INSTAGRAM" per ottenere tag o MEDIA per recuperare i dati JSON utilizzando il metodo iniziale non ha funzionato. All'interno del mio servlet per fare ottenere usando url come ad esempio api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN l'unico metodo trovato QUI ha funzionato

Grazie a tutti i collaboratori

        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());
 6
Author: lejallec, 2014-07-19 02:49:52

Per inviare una chiamata di richiesta POST:

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

Se si desidera inviare il testo nella richiesta utilizzare:

        java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(connection.getOutputStream());
        wr.write(textToSend);
        wr.flush();
 2
Author: Dimitris, 2014-02-28 09:45:03

Mi sono imbattuto in questo problema oggi e nessuna delle soluzioni pubblicate qui ha funzionato. Tuttavia, il codice pubblicato qui ha funzionato per una richiesta 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());

}

Si scopre che non è l'autorizzazione che è il problema. Nel mio caso, era un problema di codifica. Il tipo di contenuto di cui avevo bisogno era application / json ma dalla documentazione Java:

static String encode(String s, String enc)
Translates a string into application/x-www-form-urlencoded format using a specific encoding scheme.

La funzione encode traduce la stringa in applicazione / x-www-form-urlencoded.

Ora se non si imposta un tipo di contenuto, è possibile ottenere un errore di tipo di supporto non supportato 415. Se lo si imposta su application/json o qualsiasi cosa che non sia application/x-www-form-urlencoded , si ottiene una IOException. Per risolvere questo problema, evita semplicemente il metodo encode.

Per questo particolare scenario, dovrebbe funzionare quanto segue:

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

Un'altra piccola informazione che potrebbe essere utile sul perché il codice le interruzioni durante la creazione del lettore bufferizzato sono dovute al fatto che la richiesta POST viene effettivamente eseguita solo quando conn.Si chiama getInputStream().

 1
Author: Harvinder, 2014-04-15 03:36:43

Sull'API 22 L'uso della coppia BasicNamevalue è depricated, invece usa HASMAP per quello. Per saperne di più su HasMap visita qui maggiori informazioni su 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);
    }
}

E basta chiamare la funzione quando è necessario ottenere i dati dal server per posta o ottenere in questo modo

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

                        }
                    });

Ora è completo.Divertiti!!! Commentalo se trovi qualche problema.

 1
Author: yubaraj poudel, 2015-08-02 11:34:46

L'autorizzazione HTTP non differisce tra le richieste GET e POST, quindi presumo innanzitutto che qualcos'altro sia sbagliato. Invece di impostare direttamente l'intestazione di autorizzazione, suggerirei di utilizzare la classe java.net.Authorization, ma non sono sicuro che risolva il tuo problema. Forse il tuo server è in qualche modo configurato per richiedere uno schema di autorizzazione diverso da "basic" per le richieste post?

 0
Author: jarnbjo, 2010-01-08 12:07:38

Stavo cercando informazioni su come fare una richiesta POST. Devo specificare che mi request è una richiesta POST perché sto lavorando con i servizi Web RESTful che utilizzano solo metodi POST e, se la richiesta non è post, quando provo a fare la richiesta ricevo un errore HTTP 405. Assicuro che il mio codice non è sbagliato nel fare il prossimo: creo un metodo nel mio servizio web che viene chiamato tramite GET request e punto la mia applicazione a consumare quel metodo di servizio Web e funziona. Il mio codice è il successivo:

    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());
 0
Author: Oscar, 2010-01-29 20:18:34