【问题标题】:How to add authentication token in header in Picasso library如何在 Picasso 库的标头中添加身份验证令牌
【发布时间】:2014-11-25 09:35:45
【问题描述】:

我正在使用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);

问题

我调试了我的代码,发现它从未调用过 OkHttpDownloader 的 openconnection 覆盖方法,所以我的请求总是失败,最后它调用 onBitmapFailed。

请帮助我必须做些什么才能正确传递标头值。

提前致谢。

【问题讨论】:

    标签: android picasso okhttp


    【解决方案1】:

    解决这个问题花了两天时间。对于自定义下载器,您不必调用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);
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,但在我的情况下,我忘记了我的服务器上有一个自签名证书,所以 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;
          }
      }
      

      【讨论】:

        【解决方案3】:
        Picasso picasso;
        Builder builder = new Picasso.Builder(this);
        picasso = builder.loader(new BasicAuthOkHttpLoader(this)).build();
        

        将 Loader 实现为 BasicAuthOkHttpLoader 类。

        在 override Load 方法中,编写你的认证逻辑。

         @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

        【讨论】:

        • 该代码中的某些类已被弃用。请指定我应该用于这些的 picasso 和 okhttp 库的版本。
        • picasso-1.1.1.jar 可用
        【解决方案4】:

        我使用了另一个库 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);
            }
        }
        

        【讨论】:

          【解决方案5】:

          Picasso 2.5,okHttpDownloader 发生了变化。请参考以下链接添加身份验证标头

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

          【讨论】:

            【解决方案6】:

            这终于对我有用,只需调用它,然后使用 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();
            }
            

            【讨论】:

              猜你喜欢
              • 2014-08-08
              • 1970-01-01
              • 1970-01-01
              • 2018-11-13
              • 2021-08-17
              • 1970-01-01
              • 2018-11-29
              • 1970-01-01
              • 2018-12-29
              相关资源
              最近更新 更多