Android Picasso 库,如何添加身份验证标头?

Posted

技术标签:

【中文标题】Android Picasso 库,如何添加身份验证标头?【英文标题】:Android Picasso library, How to add authentication headers? 【发布时间】:2014-08-08 01:18:21 【问题描述】:

我尝试使用自定义身份验证器设置自定义 OkHttpClient,但是正如文档所说:“响应来自远程 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'

谢谢!

【问题讨论】:

【参考方案1】:

由于 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

【讨论】:

在第一行中,您在 'OkHttpClient();' 之前错过了 'new' 请注意,最新的okhttpclient版本为3,与毕加索2不兼容。如果你想使用这个解决方案,你需要okhttpclient 2。 networkInterceptors是OkHttp3中的不可变列表,不能直接添加,需要使用builder。 OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); builder.networkInterceptors().add(...) ; client = builder.build(). 可以从github.com/JakeWharton/picasso2-okhttp3-downloader获取OkHttp3Downloader 另外请注意,当你使用新的毕加索实例时,不要使用 .with(context),因为这会撤消自定义拦截器。【参考方案2】:

请参阅bryant1410's answer 了解更新的解决方案。


这样的事情可以完成设置 API-key 标头的工作:

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;
        
    

【讨论】:

明天试试!!谢谢,它看起来是一个非常简洁的解决方案! 你确定这有效吗?我得到 NoSuchMethodError: No static method source(Ljava/io/File;)Lokio/Source; Lokio/Okio 班;或其超类('okio.Okio' 的声明出现在 /system/framework/okhttp.jar 中)。 抱歉回复晚了,但您的解决方案效果很好!谢谢! 不起作用,因为方法 openConnection 不能再被覆盖... :/ @martyonair 这就是为什么我特别提到bryant1410's answer。【参考方案3】:

您还可以按照documentation of 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 后,它会使用我的身份验证器重复调用。在应用程序端日志看起来都不错。当我切换到 Interceptor 而不是 Authenticator 时,我不再在服务器日志中看到 401。【参考方案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'

【讨论】:

【参考方案5】:

这样的简单方法将保留默认的 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() 不公开

以上是关于Android Picasso 库,如何添加身份验证标头?的主要内容,如果未能解决你的问题,请参考以下文章

Android 网络图片加载缓存处理库ImageLoader和Picasso

Android Picasso图片加载库源码剖析

Android Picasso图片加载库源码剖析

第三方开源库--> Picasso

Android:如何在 Glide 或 Picasso 的占位符中使用 TextView

Android开源框架——Picasso