我创建了一个加载 WebView 的应用程序。为了登录,该网站需要基本身份验证。当我尝试通过默认浏览器访问该网站时,我收到一个弹出框,提示我输入我的用户名和密码。
如果我尝试通过我的应用程序访问该网站,我会收到错误 401 并且没有弹出窗口。我想知道是否有人可以帮助我?
我创建了一个加载 WebView 的应用程序。为了登录,该网站需要基本身份验证。当我尝试通过默认浏览器访问该网站时,我收到一个弹出框,提示我输入我的用户名和密码。
如果我尝试通过我的应用程序访问该网站,我会收到错误 401 并且没有弹出窗口。我想知道是否有人可以帮助我?
我认为比 Patrick 描述的更优雅的解决方案是使用onReceivedHttpAuthRequest
WebViewClient 的方法,如下所述:http: //www.mail-archive.com/android-developers@googlegroups.com/msg30468.html
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
handler.proceed("username", "password");
}
该网站需要身份验证。
首先你对错误做出反应:
webview.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
if (errorCode == 401) {
// show alert to enter username and password
// then when those are entered in the alert,
// set it through the setHttpAuthUsernamePassword(...) shown below
// and then reload the site
}
}
});
使用此功能设置用户和密码:WebView.setHttpAuthUsernamePassword()
webview.setHttpAuthUsernamePassword(host, realm, username, password);
都是字符串。有关主机和领域含义的更多信息,请参见上面的链接。
在此处找到解决方案:向 WebView 提供一些基本的身份验证凭据?
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
handler.proceed("USERNAME", "PASSWORD");
}
我认为它对 WebView 上的 401 错误很有帮助。
我知道这很旧,但是在此处添加另一种方法(使用 onReceivedHttpAuthRequest)对我不起作用。具体来说,有些网页不会提示用户进行基本身份验证,它们只是重定向到登录屏幕。在我的测试中,Grafana 默认情况下恰好有这种行为。
因此,我使用以下代码添加了一个 HTTP Basic auth 标头:
HashMap<String, String> headers = new HashMap<>();
String basicAuthHeader = android.util.Base64.encodeToString((username + ":" + password).getBytes(), android.util.Base64.NO_WRAP);
headers.put("Authorization", "Basic " + basicAuthHeader);
webView.loadUrl(url, headers);
这应该绕过身份验证提示并自动设置凭据。希望这可以帮助寻找另一种解决方案的人。
此外,对于希望使用“https://username:password@url”的 URL 模式的任何人 - 这已被弃用,我认为大多数浏览器会忽略它并丢弃凭据。
编辑
我已经意识到我的上述解决方案仅适用于第一个请求,并且在页面加载后没有后续请求(即对于加载的任何进一步的资源)。
为了使所有后续请求都能正常工作,我必须为 Web 客户端覆盖以下函数:
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request){
if (username != null && password != null && username.length() > 0 && password.length() > 0) {
try {
OkHttpClient client = new OkHttpClient();
Request.Builder newRequestBuilder = new Request.Builder()
.url(request.getUrl().toString());
// add headers
Map<String, String> currentHeaders = request.getRequestHeaders();
for (String header : currentHeaders.keySet()){
newRequestBuilder.addHeader(header, currentHeaders.get(header));
}
String basicAuthHeader = android.util.Base64.encodeToString((username + ":" + password).getBytes(), android.util.Base64.NO_WRAP);
newRequestBuilder.addHeader("Authorization", "Basic "+basicAuthHeader);
//make request
Request newRequest = newRequestBuilder.build();
Response response = client.newCall(newRequest).execute();
// respond with content
return new WebResourceResponse(response.header("content-type"), response.header("content-encoding", "utf-8"), response.body().byteStream());
} catch (Exception e) {
// if an exception occurs, just make a default request
return null;
}
} else {
// if no username and password, then make a default request
return null;
}
}
不幸的是,这段代码不会拦截 POST 请求,只会拦截 GET 请求,这限制了你可以用它做什么。
此外,上面的代码应该添加一些逻辑,以在附加授权标头之前验证初始请求的域与拦截请求的域匹配。否则,授权标头将与所有可能无意将其发送到不同域的请求一起发送(例如,从 CDN 加载资源)。
这对我有用添加用户名/通过 WebViewClient 然后 setWebViewClient
webView.setWebViewClient(new MyWebViewClient ());
//add this class in main activity
class MyWebViewClient extends WebViewClient {
@Override
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
handler.proceed("your username", "your password");
}
}
使用这个函数onReceivedHttpAuthRequest。它通知主机应用程序 WebView 收到了 HTTP 身份验证请求。宿主应用程序可以使用提供的HttpAuthHandler来设置 WebView 对请求的响应。默认行为是取消请求。
下面是用Kotlin编写的示例
override fun onReceivedHttpAuthRequest(
view: WebView,
handler: HttpAuthHandler,
host: String,
realm: String
) {
handler.proceed("username", "password")
}