安卓Picasso库,如何添加认证头?

37

我尝试使用自定义的OkHttpClient和自定义的Authenticator,但是文档上说:“响应来自远程Web或代理服务器的身份验证挑战。”这意味着我必须为每个图像进行2个请求,这并不理想。

是否有像Retrofit那样的请求拦截器?或者我在OkHttpClient中漏掉了什么吗?

我正在使用最新版本:

compile 'com.squareup.picasso:picasso:2.3.2'
compile 'com.squareup.okhttp:okhttp:2.0.+'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
compile 'com.squareup.okio:okio:1.0.0'

谢谢!

5个回答

97
自 Picasso 2.5.0 版本以来,OkHttpDownloader 类已经发生了变化,假设您正在使用 OkHttp3(因此使用picasso2-okhttp3-downloader),因此您需要这样做:
OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder()
                        .addHeader("X-TOKEN", "VAL")
                        .build();
                return chain.proceed(newRequest);
            }
        })
        .build();

Picasso picasso = new Picasso.Builder(context)
        .downloader(new OkHttp3Downloader(client))
        .build();

来源: https://github.com/square/picasso/issues/900


2
在第一行中,您忘记了在“OkHttpClient();”之前加上“new”。 - Mieszko
2
请注意,最新的okhttpclient版本为3,与picasso 2不兼容。如果您想使用此解决方案,则需要okhttpclient 2。 - user1354603
2
networkInterceptors 是 OkHttp3 中的不可变列表,您不能直接向其添加内容,需要使用构建器。OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); builder.networkInterceptors().add(...) ; client = builder.build() - pwightman
3
你可以从 https://github.com/JakeWharton/picasso2-okhttp3-downloader 获取 OkHttp3Downloader。 - darwin
6
请注意,在使用新的 Picasso 实例时,不要使用 .with(context),因为这会撤销自定义拦截器。 - Donavan White
显示剩余3条评论

9

请查看bryant1410的答案,获取更为更新的解决方案。


以下代码段可设置API密钥标头:

public class CustomPicasso {

    private static Picasso sPicasso;

    private CustomPicasso() {
    }

    public static Picasso getImageLoader(final Context context) {
        if (sPicasso == null) {
            Picasso.Builder builder = new Picasso.Builder(context);
            builder.downloader(new CustomOkHttpDownloader());
            sPicasso = builder.build();
        }
        return sPicasso;
    }

    private static class CustomOkHttpDownloader extends OkHttpDownloader {

        @Override
        protected HttpURLConnection openConnection(final Uri uri) throws IOException {
            HttpURLConnection connection = super.openConnection(uri);
            connection.setRequestProperty(Constants.HEADER_X_API_KEY, "MY_API_KEY");
            return connection;
        }
    }
}

明天试试看!谢谢,这看起来是一个相当不错的解决方案! - gonzalomelov
你确定这个能工作吗?我尝试了一下,但是出现了 NoSuchMethodError: No static method source(Ljava/io/File;)Lokio/Source; in class Lokio/Okio; or its super classes (declaration of 'okio.Okio' appears in /system/framework/okhttp.jar) 的错误。 - David Corsalini
1
抱歉回复晚了,但你的解决方案非常好!谢谢! - gonzalomelov
无法工作,因为方法_openConnection_不能再被覆盖了... :/ - martyglaubitz
正因为如此,我特别提到了bryant1410的答案 - nhaarman

4
你可以按照OkHttp的文档建议,添加认证功能。
只需添加以下客户端:
final OkHttpClient client = new OkHttpClient.Builder()
                .authenticator(new Authenticator() {
                    @Override
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = okhttp3.Credentials.basic("user", "pw");
                        return response.request().newBuilder()
                                .header("Authorization", credential)
                                .build();
                    }
                })
                .build();

像毕加索这样:
final Picasso picasso = new Picasso.Builder(this)
                .downloader(new OkHttp3Downloader(client))
                .build();
Picasso.setSingletonInstance(picasso);

唯一需要的依赖项是:
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'

这个程序可以运行,但是我在服务器日志中发现的唯一问题是,当我请求下载图像时,它首先尝试不带认证头进行,然后在服务器返回401后,再用我的验证器重复调用。在应用程序端的日志中看起来一切都很好。当我使用拦截器而不是验证器时,服务器日志中就不会再出现401了。 - Galeen

4

它正在运行

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                           .authenticator(new Authenticator()
                           {
                               @Override
                               public Request authenticate(Route route, Response response) throws IOException
                               {
                                   String credential =  Credentials.basic("username","password");
                                   return response.request().newBuilder()
                                           .header("Authorization", credential)
                                           .build();
                               }
                           }).build();

                   Picasso picasso = new Picasso.Builder(OnDemandImageCaptureActivity.this)
                           .downloader(new OkHttp3Downloader(okHttpClient))
                           .build();
                        picasso.load("http://example.com/abc.jpeg").into(ivcamera);

依赖:

compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'

0

像这样简单的方式将保持默认的OkHttpClient超时和缓存配置:

private class MyOkHttpDownloader extends OkHttpDownloader {

    public MyOkHttpDownloader(final Context context) {
        super(context);
        getClient().interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder()
                        .addHeader("X-TOKEN", "VAL")
                        .build();
                return chain.proceed(newRequest);
            }
        });
    }
}

Picasso picasso = new Picasso.Builder(context).downloader(new MyOkHttpDownloader(context)).build();

.interceptors() 不是公共的。 - MoxGeek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接