Javaを使用した認証を必要とするリモートURLへの接続


125

認証を必要とするJavaのリモートURLに接続するには 次のコードを変更して、プログラムでユーザー名/パスワードを提供できるようにして、401をスローしないようにする方法を見つけようとしています。

URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

ここで確認してください:stackoverflow.com/questions/1359689/...
WesternGun

回答:


134

次のように、httpリクエストのデフォルトのオーセンティケーターを設定できます。

Authenticator.setDefault (new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication ("username", "password".toCharArray());
    }
});

また、より柔軟性が必要な場合は、Apache HttpClientをチェックアウトしてください。これにより、より多くの認証オプション(およびセッションサポートなど)が提供されます。


4
不正な認証イベントをどのように処理しますか?[たとえば、ユーザーが何にも一致しないユーザー名とパスワードの認証資格情報を提供した場合]?
SK9、2011

2
上記のコードは機能しますが、何が起こっているかに関しては非常に暗黙的です。そこにサブクラス化とメソッドのオーバーライドが行われています。何が起こっているのかを知りたい場合は、それらのクラスのドキュメントを調べてください。ここのコードは、より明示的なjavacodegeeksです
淵田

12
グローバルに設定するのではなく、Authenticator特定のURL.openConnection()呼び出しごとに特定を設定することは可能ですか?
Yuriy Nakonechnyy

@由良:いいえ。グローバルである必要があります。ただし、スレッドローカル変数から認証情報を引き出すグローバル認証システムを設定したり、HTTP接続を確立する前にスレッドごとに認証情報を設定したりするなど、悪事を行うことはできます。
デビッドギブン

4
@YuriyNakonechnyy ...への応答として、Java 9以降を使用している場合はを呼び出すことができますHttpURLConnection.setAuthenticator()。残念ながら、Java 8以前では、AuthenticatorインスタンスはJVM全体のグローバル変数です。参照:docs.oracle.com/javase/9​​/docs/api/java/net/...
ニール・バートレット

133

ネイティブで邪魔にならない代替手段があり、それはあなたの通話に対してのみ機能します。

URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();

5
Base64クラスは、Apache Commons Codecによって提供されます。
Matthew Buckett、

この方法で私のために働いていませんでした... @James Van Huisが良かっただけの方法
ミゲルリベイロ

それらはすべてApache Commons Libsを使用しているため、Grailsや他の多くのJavaフレームワークでは「ネイティブ」です。
Wanderson Santos 2012

1
.trim()結果、またはチャンクされた出力を生成しないメソッドバリアントを呼び出さない限り、通常は機能しません。javax.xml.bind.DatatypeConverter安全のようです。
Jesse Glick 2013年

私はあなたのコードで引用されたこの答えは ありがとう
ノート-JJを

77

以下を使用することもできます。外部パッケージを使用する必要はありません。

URL url = new URL(“location address”);
URLConnection uc = url.openConnection();

String userpass = username + ":" + password;
String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());

uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();

10
私は長い間、Java標準パッケージ内のBase64エンコーダーを探していました。ありがとう
qwertzguy

Java9 + --add-modules javax.xml.bindでは、デフォルトのクラスパスからパッケージを削除したため、おそらく必要になることに注意してください。また、Java11 +では完全に削除されているため、再び外部依存関係が必要になります。それが進歩です!
Ed Randall

1
@EdRandallにはjava.util.Base64今があるので、それは確かに進歩です:)
Steven

42

プロトコルとドメインの間にユーザー名とパスワードを入力しながら通常のログインを使用している場合、これはより簡単です。また、ログインの有無にかかわらず動作します。

サンプルURL: http:// user:pass@domain.com/url

URL url = new URL("http://user:pass@domain.com/url");
URLConnection urlConnection = url.openConnection();

if (url.getUserInfo() != null) {
    String basicAuth = "Basic " + new String(new Base64().encode(url.getUserInfo().getBytes()));
    urlConnection.setRequestProperty("Authorization", basicAuth);
}

InputStream inputStream = urlConnection.getInputStream();

valerybodakからのコメントで、Android開発環境でどのように行われるかを以下に注意してください。


1
これはまさに私が過去30分間探していたものでした。どうもありがとう!
Geert Schuring、2014年

ユーザー名/パスワードに特殊文字が含まれている場合、それらをURLエンコードする必要があると思います。次に、上記のコードのスニペットでは、あなたが通過するurl.getUserInfo()thorugh URLDecoder.decode()最初(@Peterレーダーを)。
m01 2017

ありがとうございます。ただし、Androidの場合は、Base64を次のように使用する必要があります。httpConn.setRequestProperty( "Authorization"、basicAuth);
valerybodak

その補完のためにvalerybodakをありがとう!
javabeangrinder

8

Android-Java-Answerを探してここに来たので、短い要約を行います。

  1. 使用する James van Huisが示すようにjava.net.Authenticator
  2. 使用する この回答のように、Apache Commons HTTP Clientをます
  3. 基本的なjava.net.URLConnectionを使用するを、次に示すように手動でAuthentication-Headerを設定します

Androidで基本認証でjava.net.URLConnectionを使用する場合は、次のコードを試してください。

URL url = new URL("http://www.mywebsite.com/resource");
URLConnection urlConnection = url.openConnection();
String header = "Basic " + new String(android.util.Base64.encode("user:pass".getBytes(), android.util.Base64.NO_WRAP));
urlConnection.addRequestProperty("Authorization", header);
// go on setting more request headers, reading the response, etc

1
ありがとう。Android固有の答えを探していました!
スティーブンマコーミック

5

HttpsURLConnectionを使用して認証を設定できました

           URL myUrl = new URL(httpsURL);
            HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
            String userpass = username + ":" + password;
            String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
            //httpsurlconnection
            conn.setRequestProperty("Authorization", basicAuth);

この投稿から取得した変更の一部。Base64はjava.utilパッケージからのものです。


3

「Base64()。encode()」アプローチには十分注意してください。私のチームと私は、Apacheの不正な要求の問題を400件取得しました。生成された文字列の最後に\ r \ nが追加されるためです。

Wiresharkのおかげでパケットをスニッフィングすることがわかりました。

これが私たちの解決策です:

import org.apache.commons.codec.binary.Base64;

HttpGet getRequest = new HttpGet(endpoint);
getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding());

private String getBasicAuthenticationEncoding() {

        String userPassword = username + ":" + password;
        return new String(Base64.encodeBase64(userPassword.getBytes()));
    }

それが役に立てば幸い!


3

このコードを基本認証に使用します。

URL url = new URL(path);
String userPass = "username:password";
String basicAuth = "Basic " + Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);//or
//String basicAuth = "Basic " + new String(Base64.encode(userPass.getBytes(), Base64.No_WRAP));
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Authorization", basicAuth);
urlConnection.connect();


2

接続を開くコードを制御できない場合の回答を提供したいと思います。を使用しURLClassLoaderて、パスワードで保護されたサーバーからjarファイルをロードしたときのように。

Authenticator解決策は動作しますが、それは最初にパスワードなしとパスワードだけが1つを提供するために、サーバーが要求した後、サーバーに到達しようとするという欠点があるでしょう。サーバーがパスワードを必要とすることがすでにわかっている場合、これは不要なラウンドトリップです。

public class MyStreamHandlerFactory implements URLStreamHandlerFactory {

    private final ServerInfo serverInfo;

    public MyStreamHandlerFactory(ServerInfo serverInfo) {
        this.serverInfo = serverInfo;
    }

    @Override
    public URLStreamHandler createURLStreamHandler(String protocol) {
        switch (protocol) {
            case "my":
                return new MyStreamHandler(serverInfo);
            default:
                return null;
        }
    }

}

public class MyStreamHandler extends URLStreamHandler {

    private final String encodedCredentials;

    public MyStreamHandler(ServerInfo serverInfo) {
        String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword();
        this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes());
    }

    @Override
    protected URLConnection openConnection(URL url) throws IOException {
        String authority = url.getAuthority();
        String protocol = "http";
        URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile());

        HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection();
        connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);

        return connection;
    }

}

これmyによりhttp、資格情報が追加されたときに置き換えられる新しいプロトコルが登録されます。したがって、新しいものを作成するとき、URLClassLoader単に置き換えhttpmy、すべてうまくいきます。私URLClassLoaderは取るコンストラクタを提供していますURLStreamHandlerFactoryが、このファクトリは、URLがjarファイルを指している場合は使用されません。


1

Java 9以降、これを行うことができます

URL url = new URL("http://www.example.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setAuthenticator(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication ("USER", "PASS".toCharArray());
    }
});

2
setAuthenticator()メソッドが表示されていません。
WesternGun

0

ANDROD実装 ユーザー名とパスワードを使用して認証を要求するWebサービスからデータ/文字列応答を要求する完全な方法

public static String getData(String uri, String userName, String userPassword) {
        BufferedReader reader = null;
        byte[] loginBytes = (userName + ":" + userPassword).getBytes();

        StringBuilder loginBuilder = new StringBuilder()
                .append("Basic ")
                .append(Base64.encodeToString(loginBytes, Base64.DEFAULT));

        try {
            URL url = new URL(uri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.addRequestProperty("Authorization", loginBuilder.toString());

            StringBuilder sb = new StringBuilder();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = reader.readLine())!= null){
                sb.append(line);
                sb.append("\n");
            }

            return  sb.toString();

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (null != reader){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

0

私はあなたがこれをする必要があるようにそれをしました

    HttpURLConnection urlConnection;
    String url;
 //   String data = json;
    String result = null;
    try {
        String username ="danish.hussain@gmail.com";
        String password = "12345678";

        String auth =new String(username + ":" + password);
        byte[] data1 = auth.getBytes(UTF_8);
        String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
        //Connect
        urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
        urlConnection.setDoOutput(true);
        urlConnection.setRequestProperty("Content-Type", "application/json");
        urlConnection.setRequestProperty("Authorization", "Basic "+base64);
        urlConnection.setRequestProperty("Accept", "application/json");
        urlConnection.setRequestMethod("POST");
        urlConnection.setConnectTimeout(10000);
        urlConnection.connect();
        JSONObject obj = new JSONObject();

        obj.put("MobileNumber", "+97333746934");
        obj.put("EmailAddress", "danish.hussain@mee.com");
        obj.put("FirstName", "Danish");
        obj.put("LastName", "Hussain");
        obj.put("Country", "BH");
        obj.put("Language", "EN");
        String data = obj.toString();
        //Write
        OutputStream outputStream = urlConnection.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
        writer.write(data);
        writer.close();
        outputStream.close();
        int responseCode=urlConnection.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            //Read
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

        String line = null;
        StringBuilder sb = new StringBuilder();

        while ((line = bufferedReader.readLine()) != null) {
            sb.append(line);
        }

        bufferedReader.close();
        result = sb.toString();

        }else {
        //    return new String("false : "+responseCode);
        new String("false : "+responseCode);
        }

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.