Xamarin Forms Android WebView全局添加Authorization头遇401问题
我之前也踩过一模一样的坑!主页面加载时加了Authorization头能正常登录,但页面里的图片、脚本或者API请求一发起就报401,查请求头发现根本没带授权信息——这是因为WebView默认只会把你在loadUrl或者shouldOverrideUrlLoading里设置的头应用到主框架请求上,子资源请求不会自动继承这些自定义头。
下面是我亲测有效的解决方案,核心思路是拦截所有资源请求,手动给每个请求补上Authorization头:
1. 重写shouldInterceptRequest方法
这个方法可以拦截WebView发起的所有资源请求(包括主页面、子资源、XHR请求),我们在这里统一添加授权头。需要注意区分Android API版本(API 21+和旧版本方法签名不同):
先定义授权常量
private static final String AUTH_HEADER_KEY = "Authorization"; private static final String AUTH_HEADER_VALUE = "Bearer 你的令牌内容"; // 替换成实际的授权值
API 21+ 实现
@Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { // 先检查请求是否已经带了授权头,避免重复添加 boolean hasAuthHeader = false; for (String headerName : request.getRequestHeaders().keySet()) { if (AUTH_HEADER_KEY.equalsIgnoreCase(headerName)) { hasAuthHeader = true; break; } } if (!hasAuthHeader) { try { // 构建新的HTTP连接,手动添加授权头 URL url = new URL(request.getUrl().toString()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 添加Authorization头 connection.setRequestProperty(AUTH_HEADER_KEY, AUTH_HEADER_VALUE); // 复制原请求的所有其他头信息,避免丢失必要的请求参数 for (Map.Entry<String, String> headerEntry : request.getRequestHeaders().entrySet()) { connection.setRequestProperty(headerEntry.getKey(), headerEntry.getValue()); } // 同步原请求的方法(GET/POST等) connection.setRequestMethod(request.getMethod()); // 返回处理后的资源响应 return new WebResourceResponse( connection.getContentType(), connection.getContentEncoding(), connection.getInputStream() ); } catch (IOException e) { e.printStackTrace(); } } // 如果已有授权头或者处理出错,交给WebView默认处理 return super.shouldInterceptRequest(view, request); }
兼容API 21以下(可选)
如果你的应用需要适配旧版本设备,可以补充这个重载方法:
@Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { try { URL requestUrl = new URL(url); HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); connection.setRequestProperty(AUTH_HEADER_KEY, AUTH_HEADER_VALUE); return new WebResourceResponse( connection.getContentType(), connection.getContentEncoding(), connection.getInputStream() ); } catch (IOException e) { e.printStackTrace(); } return super.shouldInterceptRequest(view, url); }
2. 注意事项
- 主线程阻塞问题:
shouldInterceptRequest是在主线程执行的,如果请求的资源较大,同步发起HTTP请求可能会卡顿。如果遇到这种情况,可以考虑用异步任务处理,但需要额外逻辑将响应内容注入WebView,复杂度会高一些。 - 缓存问题:如果子资源已经被WebView缓存,可能不会触发拦截。可以通过
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE)临时禁用缓存,或者在拦截时处理缓存逻辑。 - 跨域问题:如果子资源来自其他域名,要确保目标服务器允许跨域请求,或者你的授权头符合CORS规则。
这样处理后,所有的资源请求都会带上Authorization头,就不会再出现子资源加载401的问题了!
内容的提问来源于stack exchange,提问作者Henrik
相关产品推荐
相关产品推荐

