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


Je voudrais générer une demande POST sur un serveur qui nécessite 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 censé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())); 

Lance également une IOException.

Quoi qu'il en soit, je serais très reconnaissant si quelqu'un pouvait suggérer une correction de la logique ci-dessus afin d'activer l'autorisation en utilisant PUBLIER avec UrlConnection.

Mais évidemment cela ne fonctionne pas comme il est censé le faire bien que si la même logique est utilisée pour GET request tout fonctionne bien.

Author: Adeel Ansari, 2010-01-08

8 answers

Une amende exemple trouvé ici. Powerlord a eu raison, ci-dessous , pour le POSTE dont vous avez besoin HttpURLConnection, au lieu de cela.

Ci-Dessous est 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();

Changez URLConnection en HttpURLConnection, pour le faire POST request.

    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", "*/*" );
 47
Author: Adeel Ansari, 2017-05-23 12:18:17

Je ne vois nulle part dans le code où vous spécifiez qu'il s'agit d'une requête POST. Là encore, vous avez besoin d'un java.net.HttpURLConnection pour faire ça.

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

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

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

Vaut également la peine d'indiquer que cela a fonctionné pour moi en utilisant une URL localhost avec un servlet de rappel configuré avec le nom "callback in web.URL xml et de rappel enregistrée:par exemple localhost: 8084/MyAPP/docs/insta/callback

MAIS après avoir terminé avec succès les étapes d'authentification, en utilisant le même site externe "INSTAGRAM" pour OBTENIR des balises ou des médias pour récupérer des données JSON en utilisant la méthode initiale n'a pas fonctionné. À l'intérieur de mon servlet pour obtenir en utilisant l'URL comme par exemple api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN seule la méthode trouvée ICI a fonctionné

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

Pour envoyer un appel de requête POST:

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

Si vous voulez envoyer du texte dans la requête, utilisez:

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

J'ai rencontré ce problème aujourd'hui et aucune des solutions affichées ici n'a fonctionné. Cependant, le code posté ici a fonctionné pour une requête 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 est le problème. Dans mon cas, c'était un problème d'encodage. Le type de contenu dont j'avais besoin était application / json mais à partir de 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 encode traduit la chaîne en application/x-www-form-urlencoded.

Maintenant, si vous ne définissez pas de type de contenu, vous pouvez obtenir une erreur 415 Unsupported Media Type. Si vous le réglez à application/json, ou tout ce qui n'est pas application/x-www-form-urlencoded, vous obtenez une IOException. Pour résoudre ce problème, évitez simplement la méthode d'encodage.

Pour ce scénario particulier, ce qui suit devrait 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 pourquoi le code les pauses lors de la création du lecteur mis en mémoire tampon sont dues au fait que la requête POST n'est exécutée que lorsque conn.getInputStream () est appelé.

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

Sur API 22, L'Utilisation De la paire BasicNamevalue est dépriquée, utilisez plutôt HASMAP pour cela. Pour en savoir plus sur la visite HasMap ici plus sur 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);
    }
}

Et Appelez simplement la fonction lorsque vous avez besoin d'obtenir les données du serveur soit par courrier, soit 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 terminé.Amusez-vous bien!!! Commentez-le si vous trouvez un problème.

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

L'autorisation HTTP ne diffère pas entre les requêtes GET et POST, donc je suppose d'abord que quelque chose d'autre ne va pas. Au lieu de définir directement l'en-tête Authorization, je suggère d'utiliser la classe java.net.Authorization, mais je ne sais pas si cela résout votre problème. Peut-être que votre serveur est en quelque sorte configuré pour exiger un schéma d'autorisation différent de "basic" pour les requêtes post?

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

Je cherchais des informations sur la façon de faire une demande de publication. Je dois spécifier que la demande mi est une demande POST car, je travaille avec des services Web RESTful qui utilisent uniquement les méthodes POST, et si la demande n'est pas post, lorsque j'essaie de faire la demande, je reçois une erreur HTTP 405. Je m'assure que mon code ne se trompe pas en faisant la suivante: je crée une méthode dans mon service Web qui est appelée via GET request et je pointe mon application pour consommer cette méthode de service Web et cela fonctionne. 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
Author: Oscar, 2010-01-29 20:18:34