Java: Jak używać UrlConnection do wysyłania żądań z autoryzacją?

Chciałbym wygenerować żądanie POST do serwera, który wymaga uwierzytelnienia. Próbowałem użyć następującej metody:

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

Ale serwer nie odbiera danych autoryzacji. Linia, która ma dodawać dane autoryzacji jest następująca:

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

I linia

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

Rzuca również IOException.

W każdym razie byłbym bardzo wdzięczny, gdyby ktoś mógł zasugerować jakąś poprawkę powyższej logiki w celu umożliwienia autoryzacji za pomocą POST z UrlConnection.

Ale oczywiście nie działa tak jak powinno, chociaż jeśli ta sama logika jest używana do żądania GET, wszystko działa dobrze.

Author: Adeel Ansari, 2010-01-08

8 answers

A fine przykład znaleziony tutaj . Powerlord dobrze zrozumiałem, poniżej , do postu potrzebujesz HttpURLConnection, zamiast tego.

Poniżej znajduje się kod, aby to zrobić,

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

Zmień URLConnection na HttpURLConnection, Aby wysłać żądanie POST.

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

Sugestia (...w komentarzach):

Może być też konieczne ustawienie tych właściwości,

conn.setRequestProperty( "Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "Accept", "*/*" );
 47
Author: Adeel Ansari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:17

Nie widzę nigdzie w kodzie, gdzie podajesz, że jest to żądanie POST. Z drugiej strony, Potrzebujesz java.net.HttpURLConnection żeby to zrobić.

W rzeczywistości, Gorąco polecam użycie HttpURLConnection zamiast URLConnection, z conn.setRequestMethod("POST"); i zobaczyć, czy nadal sprawia problemy.

 13
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 20:39:19

Aby wykonać uwierzytelnianie oAuth do zewnętrznej aplikacji (INSTAGRAM) Krok 3 "Pobierz token po otrzymaniu kodu" działał tylko poniższy kod

Warto również stwierdzić, że działało to dla mnie przy użyciu jakiegoś adresu URL localhost z serwletem zwrotnym skonfigurowanym z nazwą " callback in web.xml i callback URL zarejestrowane: np. localhost: 8084 / MyAPP / Docs / insta / callback

Ale po pomyślnym zakończeniu kroków uwierzytelniania, używając tej samej zewnętrznej strony "INSTAGRAM", aby uzyskać Tagi lub MEDIA do pobieranie danych JSON przy użyciu metody początkowej nie działało. Wewnątrz mojego servletu, aby uzyskać adres URL, jak np. api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN tylko metoda znaleziona tutaj zadziałała

Podziękowania dla wszystkich współpracowników

        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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-19 02:49:52

Aby wysłać zapytanie POST:

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

Jeśli chcesz wysłać tekst w żądaniu użyj:

        java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(connection.getOutputStream());
        wr.write(textToSend);
        wr.flush();
 2
Author: Dimitris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-28 09:45:03

Natknąłem się dziś na ten problem i Żadne z zamieszczonych tutaj rozwiązań nie zadziałało. Jednak kod wysłany tutaj zadziałał naPost Prośba:

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

}
Okazuje się, że to nie autoryzacja jest problemem. W moim przypadku był to problem z kodowaniem. Content-type I potrzebne było application / json ale z Dokumentacji Javy:
static String encode(String s, String enc)
Translates a string into application/x-www-form-urlencoded format using a specific encoding scheme.

Funkcja encode tłumaczy łańcuch na application / x-www-form-urlencoded.

Jeśli nie ustawisz typu zawartości, może pojawić się błąd 415 nieobsługiwanego typu multimediów. Jeśli ustawisz go na application / json lub cokolwiek, co nie jest application / x-www-form-urlencoded, otrzymasz IOException. Aby to rozwiązać, po prostu unikaj metody kodowania.

W tym konkretnym scenariuszu powinno działać:

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

Kolejna mała informacja, która może być pomocna, dlaczego kod przerwy podczas tworzenia bufferowanego czytnika są spowodowane tym, że żądanie POST jest wykonywane tylko wtedy, gdy conn.wywołana jest funkcja getInputStream () .

 1
Author: Harvinder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-15 03:36:43

W API 22 użycie pary BasicNamevalue jest depricowane, zamiast tego użyj do tego HASMAP. Aby dowiedzieć się więcej o HasMap odwiedź tutaj więcej o 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);
    }
}

I po prostu wywołaj funkcję, gdy potrzebujesz uzyskać dane z serwera pocztą lub 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);

                        }
                    });

Teraz jest kompletna.Smacznego!!! Skomentuj go, jeśli znajdziesz jakiś problem.

 1
Author: yubaraj poudel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-02 11:34:46

Autoryzacja HTTP nie różni się między żądaniami GET I POST, więc najpierw zakładam, że coś innego jest nie tak. Zamiast ustawiać bezpośrednio nagłówek Authorization, sugerowałbym użycie klasy java. net. Authorization, ale nie jestem pewien, czy to rozwiąże twój problem. Być może twój serwer jest w jakiś sposób skonfigurowany tak, aby wymagał innego schematu autoryzacji niż "podstawowy" dla żądań post?

 0
Author: jarnbjo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-08 12:07:38

Szukałem informacji o tym, jak zrobić żądanie POST. Muszę określić, że żądanie mi jest żądaniem POST, ponieważ pracuję z usługami sieciowymi RESTful, które używają tylko metod POST, a jeśli żądanie nie jest postem, podczas próby wykonania żądania otrzymuję błąd HTTP 405. Zapewniam, że mój kod nie jest zły, robiąc następny: tworzę metodę w moim serwisie internetowym, która jest wywoływana przez żądanie GET i wskazuję moją aplikację, aby korzystać z tej metody usługi internetowej i działa. Mój kod to następny:

    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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 20:18:34