私は新しいプロジェクトにOkHttpライブラリを使用していますが、その使いやすさに感銘を受けています。今、基本認証を使用する必要があります。残念ながら、動作するサンプルコードは不足しています。 HTTP 401ヘッダーが検出されたときに、ユーザー名/パスワード認証情報をOkAuthenticatorに渡す方法の例を探しています。私はこの答えを見ました:
Retrofit POST request with Basic HTTP Authentication: "ストリーミングHTTPボディを再試行できません"
しかし、それは私をあまり遠くに行かせませんでした。 OkHttp github repo のサンプルには、認証ベースのサンプルも含まれていません。誰かが私を正しい方向に導くための要点または他のコードサンプルを持っていますか?ご協力ありがとうございます!
OkAuthenticator を使用してみてください:
client.setAuthenticator(new OkAuthenticator() {
@Override public Credential authenticate(
Proxy proxy, URL url, List<Challenge> challenges) throws IOException {
return Credential.basic("scott", "tiger");
}
@Override public Credential authenticateProxy(
Proxy proxy, URL url, List<Challenge> challenges) throws IOException {
return null;
}
});
更新:
名前が Authenticator に変更されました
Okhttp3の更新コード:
import okhttp3.Authenticator;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
public class NetworkUtil {
private final OkHttpClient.Builder client;
{
client = new OkHttpClient.Builder();
client.authenticator(new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
if (responseCount(response) >= 3) {
return null; // If we've failed 3 times, give up. - in real life, never give up!!
}
String credential = Credentials.basic("name", "password");
return response.request().newBuilder().header("Authorization", credential).build();
}
});
client.connectTimeout(10, TimeUnit.SECONDS);
client.writeTimeout(10, TimeUnit.SECONDS);
client.readTimeout(30, TimeUnit.SECONDS);
}
private int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
}
更新されたコードは次のとおりです。
client.setAuthenticator(new Authenticator() {
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
String credential = Credentials.basic("scott", "tiger");
return response.request().newBuilder().header("Authorization", credential).build();
}
@Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
return null;
}
})
@agamovが指摘したように:
前述のソリューションには1つの欠点があります。httpClientには、401応答を受信した後にのみ許可ヘッダーが追加されます。
@agamovは、各リクエストに認証ヘッダーを「手動で」追加することを提案しましたが、より良い解決策があります。 Interceptor
を使用します。
import Java.io.IOException;
import okhttp3.Credentials;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class BasicAuthInterceptor implements Interceptor {
private String credentials;
public BasicAuthInterceptor(String user, String password) {
this.credentials = Credentials.basic(user, password);
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request authenticatedRequest = request.newBuilder()
.header("Authorization", credentials).build();
return chain.proceed(authenticatedRequest);
}
}
次に、すべての認証済みリクエストを作成するために使用するOkHttpクライアントにインターセプターを追加します。
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new BasicAuthInterceptor(username, password))
.build();
前述のソリューションには1つの欠点があります。httpClientは、401応答を受信した後にのみ許可ヘッダーを追加します。 api-serverとの通信は次のようになります。
すべてのリクエストにbasic-authを使用する必要がある場合は、各リクエストに認証ヘッダーを追加するか、次のようなラッパーメソッドを使用します。
private Request addBasicAuthHeaders(Request request) {
final String login = "your_login";
final String password = "p@s$w0rd";
String credential = Credentials.basic(login, password);
return request.newBuilder().header("Authorization", credential).build();
}
Base 64認証を使用したOkhttp
String endpoint = "https://www.example.com/m/auth/"
String username = "user123";
String password = "12345";
String credentials = username + ":" + password;
final String basic =
"Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
Request request = new Request.Builder()
.url(endpoint)
.header("Authorization", basic)
.build();
OkHttpClient client = SomeUtilFactoryClass.buildOkhttpClient();
client.newCall(request).enqueue(new Callback() {
...
誰かがインターセプターのKotlinバージョンを要求しました。ここに私が思いついたものがあり、それはうまく機能します:
val client = OkHttpClient().newBuilder().addInterceptor { chain ->
val originalRequest = chain.request()
val builder = originalRequest.newBuilder()
.header("Authorization", Credentials.basic("ausername", "apassword"))
val newRequest = builder.build()
chain.proceed(newRequest)
}.build()
すべての回答は良好ですが、一部のリクエストではcontent-typeが必要であるため、コンテンツを追加する必要があるとは言われていません次のようにリクエストに入力します:
Request request = new Request.Builder()
.url(url)
.addHeader("content-type", "application/json")
.post(body)
.build();
追加しない場合、nauthorizedメッセージが表示され、修正に多くの時間を費やすことになります。
Android DjangoのようなトークンでWordをトークンに追加する必要があります
Request request = new Request.Builder()
.url(theUrl)
.header("Authorization", "Token 6utt8gglitylhylhlfkghriyiuy4fv76876d68")
.build();
、問題のあるWordはその「トークン」です。全体として、リクエストの作成方法に関する特定のサーバーAPIのルールを注意深く確認する必要があります。
OkHttp3では、authenticator()
メソッドを追加して、OkHttpClient
自体に認証を設定します。元の呼び出しが401応答で戻った後、the authenticator()
はAuthorization
ヘッダーを追加します
new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.readTimeout(10000, TimeUnit.MILLISECONDS)
.authenticator(new Authenticator() {
@Nullable
@Override
public Request authenticate(@NonNull Route route, @NonNull Response response) {
if (response.request().header(HttpHeaders.AUTHORIZATION) != null)
return null; //if you've tried to authorize and failed, give up
String credential = Credentials.basic("username", "pass");
return response.request().newBuilder().header(HttpHeaders.AUTHORIZATION, credential).build();
}
})
.build();
より安全ですが、最初にすべての401リクエストでサーバーをスパムしたくない場合は、事前認証と呼ばれるものを使用して、リクエストで最初にAuthorization
ヘッダーを送信できます
String credentials = Credentials.basic("username", "password");
Request httpRequest = new Request.Builder()
.url("some/url")
.header("content-type", "application/json")
.header(HttpHeaders.AUTHORIZATION, credentials)
.build();
私の場合、ヘッダーに認証を統合した場合にのみ機能しました(OkHttpバージョン4.0.1):
Request request = new Request.Builder()
.url("www.url.com/api")
.addHeader("Authorization", Credentials.basic("username", "password"))
.build();
Request response = client.newCall(request).execute();
これはOkHttpクライアントのスニペットです。
OkHttpClient client = new OkHttpClient.Builder()
.authenticator(new Authenticator() {
@Override public Request authenticate(Route route, Response
response) throws IOException {
if (response.request().header("Authorization") != null) {
return null; // Give up, we've already attempted to
authenticate.
}
System.out.println("Authenticating for response: " + response);
System.out.println("Challenges: " + response.challenges());
String credential = Credentials.basic(username, password);
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
}) .build();
今すぐリクエストしてください。基本認証は、クライアントが既に持っているので行きます。
Request request = new Request.Builder().url(JIRAURI+"/issue/"+key).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("onFailure: "+e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println( "onResponse: "+response.body().string());
}
});