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

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/…
Neil Bartlett

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

나를 위해 이런 식으로 작동하지 않았다 ... @ 제임스 밴 하우스는 좋았다 만하는 방식 것을
미겔 리베

모두 Apache Commons Libs를 사용하기 때문에 Grails 및 기타 많은 Java 프레임 워크에서 '기본'입니다.
원더 슨 산토스

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
나는 오랫동안 자바 표준 패키지 내에서 Base64 인코더를 찾고 있었다! 감사합니다
qwertzguy

Java9 +의 --add-modules javax.xml.bind경우 기본 클래스 경로에서 패키지를 제거 했으므로 아마도 필요합니다 . 그리고 Java11 +에서는 완전히 제거되었으므로 외부 종속성이 다시 필요합니다. 이것이 진보입니다!
Ed Randall

1
@EdRandall있다 java.util.Base64가 :) 참으로 진행 그래서 지금
스티븐 Schlansker

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

Android 개발 환경에서 수행되는 방법 아래의 valerybodak의 의견에 유의하십시오.


1
이것이 제가 지난 30 분 동안 검색해온 것과 정확히 일치 합니다. 감사합니다!
Geert

사용자 이름 / 비밀번호에 특수 문자가 포함 된 경우 해당 문자를 urlencode해야합니다. 그런 다음 위의 코드 스 니펫에서 먼저 url.getUserInfo()thorugh URLDecoder.decode()(@Peter Rader)를 전달합니다.
m01 2017-04-20

감사합니다.하지만 Android의 경우 다음과 같이 Base64를 사용해야합니다. String basicAuth = "Basic"+ Base64.encodeToString (url.getUserInfo (). getBytes (), Base64.DEFAULT); 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을 사용 하고 여기에 표시된 것과 같이 수동으로 인증 헤더를 설정 하십시오.

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 특정 답변을 찾고있었습니다!
Stephen McCormick

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 ()"접근 방식에주의하십시오. 우리 팀과 저는 생성 된 문자열 끝에 \ r \ n을 추가하기 때문에 400 개의 Apache 잘못된 요청 문제가 발생했습니다.

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솔루션은 작동하지만 먼저 암호없이 서버에 도달하려고 시도하고 서버가 암호를 요청한 후에 만 ​​암호를 제공한다는 단점이 있습니다. 서버에 비밀번호가 필요하다는 것을 이미 알고 있다면 불필요한 왕복입니다.

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그냥 교체 http하면 my모든 것이 좋습니다. 알아URLClassLoader 를 사용하는 생성자를 제공 URLStreamHandlerFactory하지만,이 공장은 jar 파일에 대한 URL 포인트 경우 사용되지 않습니다.


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 IMPLEMENTATION 사용자 이름과 암호로 인증을 요청하는 웹 서비스에서 데이터 / 문자열 응답을 요청하는 완전한 방법

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.