有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用安卓中的okhttp在webview中发送每个请求的授权头

我正在使用WebView显示网页,但服务器希望来自我的WebView的每个请求都有一个授权令牌。有人知道这是否可能吗? 我在#SOadding-header-to-all-request-with-retrofit-2中引用了这篇文章。但是我不能得到结果

这是我的代码(与我的编码标准完全一致,我是初学者)

    public class TableViewTest extends AppCompatActivity {

    ScrollView scrollView;
    WebView webView;
    SharedPreferences pref;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_table_view_test);

        //final ProgressDialog pd = ProgressDialog.show(this, "", "Loading...", true);


        webView = (WebView) findViewById(R.id.webView1Id)

        webView.setVerticalScrollBarEnabled(true);
        webView.setHorizontalScrollBarEnabled(true);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setBuiltInZoomControls(true);

        webView.setWebViewClient(new WebViewClient() {

            @SuppressWarnings("deprecation")
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //return true load with system-default-browser or other browsers, false with your webView

                pref = getSharedPreferences("app", Context.MODE_PRIVATE);
                final String acToken = pref.getString("token", "DEFAULT");


                HashMap<String, String> headerMap = new HashMap<>();
                //put all headers in this header map
                headerMap.put("Authorization", acToken);


                view.loadUrl(url, headerMap);


                return false;
            }

            @Override
            public void onLoadResource(WebView view, String url) {
                super.onLoadResource(view, url);
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }
        });

        webView.loadUrl("myurl");

    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        webView.saveState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        webView.restoreState(savedInstanceState);
    }


    public WebViewClient getWebViewClientWithCustomHeader(){

        pref = getSharedPreferences("app", Context.MODE_PRIVATE);
        final String acToken = pref.getString("token", "DEFAULT");

        return new WebViewClient() {

            @SuppressWarnings("deprecation")
            public WebResourceResponse shouldInterceptRequest(WebView view, String url){
                try {
                    OkHttpClient okHttpClient = new OkHttpClient();
                    Request request = new Request.Builder().url(url).addHeader("Authorization" , "Bearer " + acToken)
                            .build();

                    Response response = okHttpClient.newCall(request).execute();

                    return new WebResourceResponse(response.header("content-type", response.body().contentType().type()), // You can set something other as default content-type
                            response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                            response.body().byteStream());


                } catch (ClientProtocolException e) {
                    //return null to tell WebView we failed to fetch it WebView should try again.
                    return null;
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        };
    }
}

谢谢你的帮助

编辑

现在我能够得到服务器的响应,但是在纯html中,没有正确地呈现css,我不知道为什么

这是新代码

    public class TableViewTest extends AppCompatActivity {

    ScrollView scrollView;
    WebView webView;
    SharedPreferences pref;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_table_view_test);

        //final ProgressDialog pd = ProgressDialog.show(this, "", "Loading...", true);

        String url = "myurl";
        pref = getSharedPreferences("app", Context.MODE_PRIVATE);


        webView = (WebView) findViewById(R.id.webView1Id);

        webView.setVerticalScrollBarEnabled(true);
        webView.setHorizontalScrollBarEnabled(true);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.setWebViewClient(wvc);

        webView.loadUrl("myurl");

    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        webView.saveState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        webView.restoreState(savedInstanceState);
    }


    public WebViewClient wvc =  new WebViewClient() {

            @SuppressWarnings("deprecation")
            public WebResourceResponse shouldInterceptRequest(WebView view, String url){
                try {
                    final String acToken = pref.getString("token", "DEFAULT");

                    OkHttpClient okHttpClient = new OkHttpClient();
                    Request request = new Request.Builder().url(url).addHeader("Authorization" , "Bearer " + acToken)
                            .build();

                    Response response = okHttpClient.newCall(request).execute();

                    return new WebResourceResponse(response.header("content-type", response.body().contentType().type()), // You can set something other as default content-type
                            response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                            response.body().byteStream());


                } catch (ClientProtocolException e) {
                    //return null to tell WebView we failed to fetch it WebView should try again.
                    return null;
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        };
}

在stacktrace中找到了这个,在stacktrace中没有更多

 E/DataReductionProxySettingListener: No DRP key due to exception:java.lang.ClassNotFoundException: com.安卓.webview.chromium.Drp

共 (3) 个答案

  1. # 1 楼答案

    最后,这将纠正html呈现问题(对不起,我之前没有注意到这一点)

    更改中的content-type

    return new WebResourceResponse(response.header("content-type", response.body().contentType().type()), // You can set something other as default content-type
                            response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                            response.body().byteStream());
    

    text/html,因此新代码是

    return new WebResourceResponse(response.header("text/html", response.body().contentType().type()), // You can set something other as default content-type
                        response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                        response.body().byteStream());
    

    如果我的解决方案需要任何修改,请随意编辑。总是接受更好的解决方案。快乐编码。。。感谢所有愿意帮忙的人

  2. # 2 楼答案

    Sudheesh的回答很好,以下是更新版本,因为shouldOverrideUrlLoading(WebView view, String url)在API 21中被弃用:

    webView.setWebViewClient(new WebViewClient() {
                public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest webResourceRequest) {
                    // Filter out any requests we not interested in
                    if (webResourceRequest.getUrl().getHost() == null ||
                            !webResourceRequest.getUrl().getHost().equals(MyAPI.getServer().toHost())) {
                        return super.shouldInterceptRequest(view, webResourceRequest);
                    }
                    try {
                        OkHttpClient okHttpClient = new OkHttpClient();
                        Request request = new Request.Builder().url(webResourceRequest.getUrl().toString())
                                .addHeader(HttpConnector.DefaultConnector().getAuthorizationHeaderKey(), HttpConnector.DefaultConnector().getAuthorizationHeaderValue())
                                .build();
                        Response response = okHttpClient.newCall(request).execute();
                        return new WebResourceResponse(response.header("text/html", response.body().contentType().type()), // You can set something other as default content-type
                                response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                                response.body().byteStream());
                    } catch (ClientProtocolException e) {
                        //return null to tell WebView we failed to fetch it WebView should try again.
                        return null;
                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                }
            });
    
  3. # 3 楼答案

    这可能不能回答你的问题,但我认为这对其他有类似问题的人会有帮助

    如果服务器资源需要这样的基本身份验证头Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=,那么您应该像这样重写WebViewClient中的onReceivedHttpAuthRequest方法

    webView.webViewClient = object : WebViewClient() {
    
        override fun onReceivedHttpAuthRequest(view: WebView?, handler: HttpAuthHandler?, host: String?, realm: String?) {
            handler?.proceed("username", "password")
        }
    
    }
    

    还请注意,如果可能,您应该始终避免拦截WebView请求。阅读更多关于它的信息here