如何在Picasso库的头文件中添加身份验证令牌

时间:2014-09-30 16:59:54

标签: android picasso okhttp

我正在使用picasso库来下载位图,因此在api中我需要在标头中传递令牌。我试过这个帖子Android Picasso library, How to add authentication headers?

下面的代码
public static Picasso getImageLoader(final Context context) {
    // fetch the auth value
    sSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());

    Picasso.Builder builder = new Picasso.Builder(context);
    builder.downloader(new OkHttpDownloader(context) {
        @Override
        protected HttpURLConnection openConnection(Uri uri) throws IOException {
            HttpURLConnection connection = super.openConnection(uri);
            connection.setRequestProperty(Constant.HEADER_X_API_KEY, sSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
            return connection;
        }
    });
    sPicasso = builder.build();
    return sPicasso;
}

毕加索请求

mTarget = new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
        mdpImageView.setImageBitmap(bitmap);
        Logger.d(TAG, "Test");
    }

    @Override
    public void onBitmapFailed(Drawable drawable) {
        Logger.d(TAG, "Test");
    }

    @Override
    public void onPrepareLoad(Drawable drawable) {
        Logger.d(TAG, "Test");
    }
};

CustomPicasso.getImageLoader(getActivity()).with(getActivity()).load(URL).into(mTarget);

问题

我调试了我的代码&我看到它从未调用openconnection的{​​{1}}覆盖方法,所以我的请求总是失败&最后它调用OkHttpDownloader

请帮助我正确传递标题值所需要做的事情。

提前致谢。

6 个答案:

答案 0 :(得分:7)

花了两天时间来解决这个问题。对于自定义下载程序,您无需调用with方法,因为这会初始化默认下载程序&毕加索实例。只需在下面这样做就可以帮助你获得位图。

Picasso.Builder builder = new Picasso.Builder(getActivity());
picasso =  builder.downloader(new OkHttpDownloader(getActivity()) {
    @Override
    protected HttpURLConnection openConnection(Uri uri) throws IOException {
        HttpURLConnection connection = super.openConnection(uri);
        connection.setRequestProperty(Constant.HEADER_X_API_KEY, mSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
        return connection;
    }
}).build();
picasso.load(url).into(mTarget);

答案 1 :(得分:1)

我有同样的问题,但在我的情况下,我忘记了我的服务器上有一个自签名证书,所以OkHttp获得了证书,然后拒绝检索任何图像。因此,从服务器端来看,毕加索似乎没有提出任何要求。

所以解决方法是创建一个不测试证书的不安全的OkHttp客户端

static OkHttpClient getUnsafeOkHttpClient() {
  try {
      // Create a trust manager that does not validate certificate chains
      final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
          @Override
          public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
                  String authType) throws CertificateException {
          }

          @Override
          public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
                  String authType) throws CertificateException {
          }

          @Override
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
              return null;
          }
      } };

      // Install the all-trusting trust manager
      final SSLContext sslContext = SSLContext.getInstance("SSL");
      sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
      // Create an ssl socket factory with our all-trusting manager
      final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

      OkHttpClient okHttpClient = new OkHttpClient();
      okHttpClient.setSslSocketFactory(sslSocketFactory);
      okHttpClient.setHostnameVerifier(new HostnameVerifier() {
          @Override
          public boolean verify(String hostname, SSLSession session) {
              return true;
          }
      });

      return okHttpClient;
  } catch (Exception e) {
      throw new RuntimeException(e);
  }
}

然后在我的CustomOkHttpDownloader中使用它:

static class CustomOkHttpDownloader extends OkHttpDownloader {

    private String accessToken;

    public CustomOkHttpDownloader(Context context, String accessToken) {
        super(getUnsafeOkHttpClient());
        this.accessToken = accessToken;
    }

    @Override
    protected HttpURLConnection openConnection(final Uri uri) throws IOException {
        HttpURLConnection connection = super.openConnection(uri);
        connection.setRequestProperty("Authorization", "Bearer " + accessToken);
        Log.d(LOG_TAG, "Creating connection for " + uri + " with " + accessToken);
        return connection;
    }
}

答案 2 :(得分:0)

Picasso picasso;
Builder builder = new Picasso.Builder(this);
picasso = builder.loader(new BasicAuthOkHttpLoader(this)).build();

将Loader实现为BasicAuthOkHttpLoader类。

在覆盖Load方法中,编写ur身份验证逻辑。

 @Override
  public Response load(String url, boolean localCacheOnly) throws IOException {
    HttpURLConnection connection = client.open(new URL(url));
    String authString = "username:password";
    String authStringEnc = Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP);
    connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
    connection.setUseCaches(true);

    // no caching happens without this setting in our scenario
    connection.setRequestProperty("Cache-Control", "max-stale=2592000");// 30 days
    if (localCacheOnly) {
      connection.setRequestProperty("Cache-Control", "only-if-cached");
    }

    boolean fromCache = parseResponseSourceHeader(connection.getHeaderField(RESPONSE_SOURCE));

    return new Response(connection.getInputStream(), fromCache);
  }

有关详情:http Basic auth the implementation of a custom loader

答案 3 :(得分:0)

我使用了另一个库AQuery,并且不仅可以在几分钟内获得对picassa滚动的授权访问权限,而且库也使用了手机凭证,因此非常容易。

即使您不使用此库,也请查看我如何获得仅包含下面所需字段的实验方法。较小的结果使得网络io更快,CPU的差异也很大。由于JSON较小,因此解析速度较快,或者xml的DOM较小,因此构建速度非常快。

我在这里使用的实验方法只为XML中的用户返回我想要的公开相册字段。

GoogleHandle handle = new GoogleHandle(this.getActivity(),
            AQuery.AUTH_PICASA, AQuery.ACTIVE_ACCOUNT);

    // experimental fields method encoding the data part of the query string only.
    String url = "";
    try {
        url = "https://picasaweb.google.com/data/feed/api/user/default?kind=album&access=public&fields="
                + URLEncoder
                        .encode("entry(title,id,gphoto:numphotosremaining,gphoto:numphotos,media:group/media:thumbnail)",
                                "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        //whatever I know this will work
        // I hard coded the string.
    }


        aq.auth(handle).progress(R.id.pbTrackerAlbumsProgress)
                .ajax(url, XmlDom.class, this, "renderAlbums");



public void renderAlbums(String url, XmlDom xml, AjaxStatus status) {
    List<PicasaAlbum> entries = convertAll(xml);


    if (entries.size() > 0) {
        isAuthError = false;
        // if the xml iis null we can't display the list
        // we can setup the adapter
        aa = new ArrayAdapter<PicasaAlbum>(this.getActivity(),
                R.layout.listview_item_album, entries) {

            public View getView(int position, View convertView,
                    ViewGroup parent) {

                if (convertView == null) {

                    // convertView =
                    // View.inflate(getActivity().getBaseContext(),
                    // R.layout.listview_item_album, parent);
                    convertView = getActivity().getLayoutInflater()
                            .inflate(R.layout.listview_item_album, parent,
                                    false);
                }

                PicasaAlbum picasaAlbum = getItem(position);

                AQuery aqLocal = aq.recycle(convertView);

                aqLocal.id(R.id.albumTitle).text(picasaAlbum.title);
                // aq.id(R.id.meta).text(picasaAlbum.author);

                String tbUrl = picasaAlbum.thumbNailUrl.toString();

                Bitmap placeholder = aqLocal
                        .getCachedImage(R.drawable.ic_launcher2);

                if (aqLocal.shouldDelay(position, convertView, parent,
                        tbUrl)) {

                    aqLocal.id(R.id.tb).image(placeholder);
                } else {
                    aqLocal.id(R.id.tb).image(tbUrl, true, true, 0,
                            R.drawable.ic_launcher2x, placeholder,
                            AQuery.FADE_IN_NETWORK, 0);
                }

                return convertView;

            }

        };
        ((TextView) view.findViewById(R.id.tvTrackerExistingAlbum))
                .setText("Select the album for route marker photos");
        ((ProgressBar) view.findViewById(R.id.pbTrackerAlbumsProgress))
                .setVisibility(View.GONE);
        ListView lv = (ListView) view.findViewById(R.id.lvTrackerAlbums);

        lv.setAdapter(aa);
        aa.notifyDataSetChanged();
        lv.setVisibility(View.VISIBLE);
    }
}

答案 4 :(得分:0)

Picasso 2.5,okHttpDownloader已经改变。请参阅以下链接添加身份验证标题

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

答案 5 :(得分:0)

这最终对我有用,只需调用它然后使用picasso实例,在这里我添加一个访问令牌。但您也可以添加用户名和密码。

private void setupPicasso()
{        
    //need to set picasso up to use auth - took a while to work this out!
    final Context c = context;
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    String token = <token you got when you logged in>;
                    String authString = "Bearer "+token;                        
                    Request newRequest = chain.request().newBuilder()
                            .addHeader("Authorization", authString)
                            .build();
                    return chain.proceed(newRequest);
                }
            })
            .build();
    picasso = new Picasso.Builder(context)
            .downloader(new OkHttp3Downloader(client))
            .build();
}