在 android 中使用 okhttp 向 webview 中的每个请求发送授权 header
Send authorization header with every request in webview using okhttp in android
我正在使用 WebView 来显示网页,但服务器要求我的 Webview 发出的每个请求都有一个授权令牌。有人知道这是否可能吗?
我在#SO 中提到了这个 post。但我无法得到结果。
这是我的代码(没有我的编码标准,我是初学者)
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;
}
}
};
}
并在堆栈跟踪中找到了这个,在堆栈跟踪中仅此而已
E/DataReductionProxySettingListener: No DRP key due to exception:java.lang.ClassNotFoundException: com.android.webview.chromium.Drp
最终这将纠正 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());
如果我的解决方案需要任何修改,请随时编辑。始终接受更好的解决方案。编码愉快...感谢大家#SO 随时准备提供帮助。
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;
}
}
});
这可能无法回答您的问题,但我认为它会对遇到类似问题的其他人有所帮助。
如果服务器资源需要基本身份验证 header 像这样 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。
我正在使用 WebView 来显示网页,但服务器要求我的 Webview 发出的每个请求都有一个授权令牌。有人知道这是否可能吗?
我在#SO
这是我的代码(没有我的编码标准,我是初学者)
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;
}
}
};
}
并在堆栈跟踪中找到了这个,在堆栈跟踪中仅此而已
E/DataReductionProxySettingListener: No DRP key due to exception:java.lang.ClassNotFoundException: com.android.webview.chromium.Drp
最终这将纠正 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());
如果我的解决方案需要任何修改,请随时编辑。始终接受更好的解决方案。编码愉快...感谢大家#SO 随时准备提供帮助。
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;
}
}
});
这可能无法回答您的问题,但我认为它会对遇到类似问题的其他人有所帮助。
如果服务器资源需要基本身份验证 header 像这样 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。