Android基本authentication的OkHttp

我正在使用OkHttp库来开发一个新项目,而且它的易用性给我留下了深刻的印象。 我现在有需要使用基本authentication。 不幸的是,工作示例代码缺乏。 我正在寻找一个如何在遇到HTTP 401标头时将用户名/密码凭据传递给OkAuthenticator的例子。 我查看了这个答案:

使用基本HTTP身份validation改进POST请求:“无法重试stream式HTTP正文”

但它并没有让我太过分。 OkHttp github repo上的示例也没有提供基于身份validation的示例。 有没有人有一个要点或其他代码示例让我指出正确的方向? 感谢你的协助!

尝试使用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

这是更新的代码:

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

更新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; } } 

上述解决scheme有一个缺点:只有在收到401响应后,httpClient才添加授权头。 以下是我与api-server的交stream情况: 在这里输入图像说明

如果您需要为每个请求使用basic-auth,那么最好将auth-header添加到每个请求中,或使用如下的包装器方法:

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

正如@agamov指出的那样:

上述解决scheme有一个缺点:只有在收到401响应后,httpClient才添加授权头

@agamovbuild议然后“手动”为每个请求添加validation头,但有一个更好的解决scheme:使用一个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客户端,您将使用它来创build所有已validation的请求:

 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new BasicAuthInterceptor(username, password)) .build(); 

Okhttp3与基地64身份validation

 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() { ... 

所有的答案都是好的,但没有人说,对于一些请求内容types是必需的,你应该添加一个内容types到你的请求是这样的:

 Request request = new Request.Builder() .url(url) .addHeader("content-type", "application/json") .post(body) .build(); 

如果你不添加它,你会得到未经授权的信息,你将浪费大量的时间来修复它。

我注意到在Android上有一些像django这样的服务器API,你应该在令牌中添加一个单词

 Request request = new Request.Builder() .url(theUrl) .header("Authorization", "Token 6utt8gglitylhylhlfkghriyiuy4fv76876d68") .build(); 

那个有问题的词就是那个“Token”。 总体而言,您应该仔细查看这些特定服务器API的规则,了解如何编写请求。