Xamarin.forms 将授权标头添加到Xamarin表单Android WebView中的所有请求
我正在尝试向webview客户端添加自定义http头(用于授权)。 它似乎在某些情况下工作,我可以登录到一个网页,而无需输入用户名和密码,我会被重定向到另一个页面。但是,当页面调用其他资源以获取填充有数据的元素时,会抛出一个错误,并调用OnReceiveDhttPeror。我得到的错误是401 unauthorized,当我查看IWebResourceRequest上的标题时,我根本看不到授权标题。 是我遗漏了什么,还是有人有同样的问题 使用Xamarin Forms 2.3.3.180和目标API 21(Android 5.0棒棒糖),使用Android 7.1牛轧糖编译 我在《邮递员》中尝试过向请求添加标题,效果非常好 渲染器:Xamarin.forms 将授权标头添加到Xamarin表单Android WebView中的所有请求,xamarin.forms,android-webview,Xamarin.forms,Android Webview,我正在尝试向webview客户端添加自定义http头(用于授权)。 它似乎在某些情况下工作,我可以登录到一个网页,而无需输入用户名和密码,我会被重定向到另一个页面。但是,当页面调用其他资源以获取填充有数据的元素时,会抛出一个错误,并调用OnReceiveDhttPeror。我得到的错误是401 unauthorized,当我查看IWebResourceRequest上的标题时,我根本看不到授权标题。 是我遗漏了什么,还是有人有同样的问题 使用Xamarin Forms 2.3.3.180和目标A
public class MyWebViewRenderer : WebViewRenderer
{
private MyWebViewClient _webViewClient;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if(_webViewClient == null)
_webViewClient = new MyWebViewClient();
Control.SetWebViewClient(_webViewClient);
Control.LongClickable = false;
Control.HapticFeedbackEnabled = false;
Control.Settings.JavaScriptEnabled = true;
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
var headers = new Dictionary<string, string>();
headers.Add("Authorization", $"Basic {base64string}")
Control.LoadUrl(Control.Url, headers);
}
}
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
WebView.SetWebContentsDebuggingEnabled(true);
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
var headers = new Dictionary<string, string>();
headers.Add("Authorization", $"Basic {base64string}")
view.LoadUrl(url, headers);
return true;
}
public override WebResourceResponse ShouldInterceptRequest(WebView view, IWebResourceRequest urlResource)
{
//headers does not always contains authorization header, so let's add it.
if (!urlResource.RequestHeaders.ContainsKey("authorization") && !urlResource.RequestHeaders.ContainsKey("Authorization"))
{
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
urlResource.RequestHeaders.Add("Authorization", $"{base64string}");
}
return base.ShouldInterceptRequest(view, urlResource);
}
public override void OnReceivedHttpError(WebView view, IWebResourceRequest request, WebResourceResponse errorResponse)
{
base.OnReceivedHttpError(view, request, errorResponse);
}
公共类MyWebViewRenderer:WebViewRenderer
{
私有MyWebViewClient webViewClient;
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
如果(_webViewClient==null)
_webViewClient=新的MyWebViewClient();
控件。SetWebViewClient(_webViewClient);
Control.LongClickable=false;
Control.HapticFeedbackEnabled=错误;
Control.Settings.JavaScriptEnabled=true;
var data=Encoding.GetEncoding(“ISO-8859-1”).GetBytes(“用户名:密码”);
var base64string=Base64.EncodeToString(数据,Base64Flags.NoWrap);
var headers=newdictionary();
headers.Add(“Authorization”,$“Basic{base64string}”)
Control.LoadUrl(Control.Url,标题);
}
}
WebViewClient:
public class MyWebViewRenderer : WebViewRenderer
{
private MyWebViewClient _webViewClient;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if(_webViewClient == null)
_webViewClient = new MyWebViewClient();
Control.SetWebViewClient(_webViewClient);
Control.LongClickable = false;
Control.HapticFeedbackEnabled = false;
Control.Settings.JavaScriptEnabled = true;
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
var headers = new Dictionary<string, string>();
headers.Add("Authorization", $"Basic {base64string}")
Control.LoadUrl(Control.Url, headers);
}
}
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
WebView.SetWebContentsDebuggingEnabled(true);
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
var headers = new Dictionary<string, string>();
headers.Add("Authorization", $"Basic {base64string}")
view.LoadUrl(url, headers);
return true;
}
public override WebResourceResponse ShouldInterceptRequest(WebView view, IWebResourceRequest urlResource)
{
//headers does not always contains authorization header, so let's add it.
if (!urlResource.RequestHeaders.ContainsKey("authorization") && !urlResource.RequestHeaders.ContainsKey("Authorization"))
{
var data = Encoding.GetEncoding("ISO-8859-1").GetBytes("username:password");
var base64string = Base64.EncodeToString(data, Base64Flags.NoWrap);
urlResource.RequestHeaders.Add("Authorization", $"{base64string}");
}
return base.ShouldInterceptRequest(view, urlResource);
}
public override void OnReceivedHttpError(WebView view, IWebResourceRequest request, WebResourceResponse errorResponse)
{
base.OnReceivedHttpError(view, request, errorResponse);
}
public override bool ShouldOverrideUrlLoading(WebView视图,字符串url)
{
WebView.SetWebContentsDebuggingEnabled(true);
var data=Encoding.GetEncoding(“ISO-8859-1”).GetBytes(“用户名:密码”);
var base64string=Base64.EncodeToString(数据,Base64Flags.NoWrap);
var headers=newdictionary();
headers.Add(“Authorization”,$“Basic{base64string}”)
LoadUrl(url、标题);
返回true;
}
公共覆盖WebResourceResponse ShouldInterceptRequest(WebView视图,iWebResourceRequestUrlResource)
{
//标头并不总是包含授权标头,所以让我们添加它。
如果(!urlResource.RequestHeaders.ContainsKey(“授权”)和&!urlResource.RequestHeaders.ContainsKey(“授权”))
{
var data=Encoding.GetEncoding(“ISO-8859-1”).GetBytes(“用户名:密码”);
var base64string=Base64.EncodeToString(数据,Base64Flags.NoWrap);
添加(“授权”、$“{base64string}”);
}
返回base.ShouldInterceptRequest(视图,urlResource);
}
public override void onReceivedHttPeror(WebView视图、IWebResourceRequest请求、WebResourceResponse errorResponse)
{
base.onReceivedHttPeror(查看、请求、错误响应);
}
如果您只需要get请求上的标题,下面的代码就可以了。然而,POST请求是另一个问题。我需要做一件类似的事情(针对所有请求,而不仅仅是GET),我所能说的是没有直接的解决方案,至少我没有找到一个(除了编写自己的网络驱动程序之外,我已经尝试了所有方法)。我尝试过很多方法(ShouldOverrideUrlLoading、ShouldInterceptRequest、CustomLoadUrl和PostUrl等),但没有一种方法能提供100%的解决方案。关于这一点有很多错误的信息,所以我认为需要澄清一下,因为我花了两天的时间都没有成功
以下是我学到的:
如果您只需要GET请求中的头,那就很简单了。只需创建一个
WebViewClient
的实现,并覆盖ShouldOverrideUrlLoading
,如下所示:
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(App.Android.HybridWebViewRenderer))]
namespace App.Android
{
public class HybridWebViewRenderer : WebViewRenderer
{
public HybridWebViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
Control.SetWebViewClient(new CustomWebViewClient());
}
}
public class CustomWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, string url)
{
Dictionary<string, string> headers = new Dictionary<string, string>
{
["Name"] = "value"
};
view.LoadUrl(url, headers);
return true;
}
}
}
[程序集:ExportRenderer(typeof(Xamarin.Forms.WebView)、typeof(App.Android.HybridWebViewRenderer))]
名称空间App.Android
{
公共类HybridWebViewRenderer:WebViewRenderer
{
公共HybridWebViewRenderer(上下文):基础(上下文)
{
}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
Control.SetWebViewClient(新的CustomWebViewClient());
}
}
公共类CustomWebViewClient:WebViewClient
{
公共覆盖bool ShouldOverrideUrlLoading(Android.Webkit.WebView视图,字符串url)
{
字典头=新字典
{
[“名称”]=“值”
};
LoadUrl(url、标题);
返回true;
}
}
}
但是,如果您需要在其他请求(特别是POST请求)中使用头,那么实际上并没有一个完美的解决方案。许多答案都告诉您要覆盖ShouldInterceptRequest
,但这不太可能有帮助ShouldInterceptRequest
提供一个IWebResourceRequest
,其中包含请求的URL、方法(即POST)和标题。有一些答案表明,通过执行request.headers.Add(“Name”、“Value”)
添加标题是可行的解决方案,但这是错误的。IWebResourceRequest
未被WebView
的内部逻辑使用,因此修改它是无用的强>
您可以在ShouldInterceptRequest
中编写自己的HTTP客户机,其中包括您自己的头,以执行请求并返回WebResourceResponse
对象。同样,这适用于GET请求,但问题是,即使我们可以拦截POST请求,我们也无法确定请求中的内容,因为请求内容不包括在IWebResourceRequest
对象中。因此,我们无法准确地手动执行请求。所以,除非POST请求的内容不重要或者可以以某种方式