web-dev-qa-db-fra.com

Java: comment utiliser UrlConnection pour poster une demande avec autorisation?

Je souhaite générer une demande POST à un serveur nécessitant une authentification. J'ai essayé d'utiliser la méthode suivante:

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

mais le serveur ne reçoit pas les données d'autorisation. La ligne qui est supposée ajouter des données d'autorisation est la suivante:

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

et la ligne 

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

jette également une exception IOException.

Quoi qu'il en soit, je serais très reconnaissant à quiconque de suggérer une solution de la logique ci-dessus afin de permettre une autorisation avec POST avec UrlConnection.

mais évidemment cela ne fonctionne pas comme il est supposé bien que si la même logique est utilisée pour la requête GET, tout fonctionne correctement.

31
Niko Gamulin

Une amende exemple trouvé ici . Powerlord vous avez bien compris, ci-dessous , pour POST, vous avez besoin de HttpURLConnection .

Ci-dessous le code pour le faire,

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

Remplacez URLConnection par HttpURLConnection, pour en faire la demande POST.

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

Suggestion (... dans les commentaires):

Vous devrez peut-être également définir ces propriétés,

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

Je ne vois nulle part dans le code où vous indiquez qu'il s'agit d'une demande POST. Là encore, vous avez besoin d’un Java.net.HttpURLConnection pour le faire. 

En fait, je recommande fortement d'utiliser HttpURLConnection au lieu de URLConnection, avec conn.setRequestMethod("POST"); et de voir si cela vous pose toujours des problèmes.

9
Powerlord

Pour faire l'authentification oAuth à une application externe (INSTAGRAM) Étape 3 "récupérez le jeton après avoir reçu le code" Seul le code ci-dessous a fonctionné pour moi

Cela vaut également la peine de préciser que cela fonctionnait pour moi en utilisant une URL locale avec un servlet de rappel configuré avec le nom "callback" dans web.xml et une URL de rappel enregistrée: par exemple localhost: 8084/MyAPP/docs/insta/callback

MAIS une fois les étapes d’authentification complétées avec succès, l’utilisation du même site externe "INSTAGRAM" pour effectuer la recherche de balises ou MEDIA pour récupérer les données JSON à l’aide de la méthode initiale ne fonctionnait pas. Dans mon servlet pour faire GET en utilisant une URL telle que Par exemple. api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN seule méthode trouvée ICI travaillé 

Merci à tous les contributeurs

        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
lejallec

Pour envoyer un appel de demande POST:

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

Si vous souhaitez envoyer du texte dans la demande, utilisez:

        Java.io.OutputStreamWriter wr = new Java.io.OutputStreamWriter(connection.getOutputStream());
        wr.write(textToSend);
        wr.flush();
2
Dimitris

Sur API 22, l'utilisation de BasicNamevalue Pair est privée, utilisez plutôt HASMAP pour cela. Pour en savoir plus sur la visite HasMap ici plus sur développeur hasmap.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);
    }
}

et il suffit d'appeler la fonction lorsque vous avez besoin d'obtenir les données du serveur par la poste ou comme ceci

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

                        }
                    });

Maintenant c'est complet.Profitez !!! Commentez-le si vous rencontrez un problème.

1
yubaraj poudel

J'ai rencontré ce problème aujourd'hui et aucune des solutions affichées ici n'a fonctionné. Cependant, le code posté ici travaillait pour une demande 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());

}

Il s'avère que ce n'est pas l'autorisation qui pose problème. Dans mon cas, c'était un problème d'encodage. Le type de contenu dont j'avais besoin était application/json _ mais d'après la documentation Java:

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

La fonction encoder traduit la chaîne en application/x-www-form-urlencoded} _.

Maintenant, si vous ne définissez pas de type de contenu, vous risquez d'obtenir une erreur de type de support 415 non pris en charge. Si vous le définissez sur application/json ou sur tout ce qui n'est pas application/x-www-form-urlencoded, vous obtenez une exception IOException. Pour résoudre ce problème, évitez simplement la méthode de codage. 

Pour ce scénario particulier, les éléments suivants doivent fonctionner:

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

Une autre petite information qui pourrait être utile pour expliquer la rupture du code lors de la création du lecteur mis en mémoire tampon est que la demande POST n'est en réalité exécutée que lorsque conn.getInputStream () est appelé.

1
Harvinder

je cherchais des informations sur la manière de faire une demande POST. Je dois spécifier que la requête mi est une requête POST, car je travaille avec des services Web RESTful qui utilisent uniquement les méthodes POST, et si la requête n'est pas postée, lorsque j'essaie de faire la request je reçois une erreur HTTP 405. Je m'assure que mon code ne se trompe pas lors de la tâche suivante: je crée une méthode dans mon service Web appelée via une requête GET et je pointe mon application pour qu'elle consomme cette méthode de service Web. Mon code est le suivant:

    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
Oscar

L'autorisation HTTP ne diffère pas entre les requêtes GET et POST, aussi je supposerais d'abord que quelque chose d'autre ne va pas. Au lieu de définir directement l'en-tête d'autorisation, je suggérerais d'utiliser la classe Java.net.Authorization, mais je ne suis pas sûr que cela résout votre problème. Peut-être que votre serveur est en quelque sorte configuré pour exiger un régime d’autorisation différent de celui de "base" pour les demandes de publication?

0
jarnbjo