Xamarin WebView原生弹窗开发:Xamarin审核默认身份验证实现代码求分享
Xamarin WebView默认身份验证功能实现方案
以下为全平台可直接复用的实现代码,支持默认自动填充身份信息、原生弹窗手动输入两种模式:
共享层自定义WebView控件
using Xamarin.Forms; namespace YourAppNamespace.Controls { public class AuthenticatedWebView : WebView { // 默认身份信息绑定属性 public static readonly BindableProperty DefaultUsernameProperty = BindableProperty.Create(nameof(DefaultUsername), typeof(string), typeof(AuthenticatedWebView), string.Empty); public static readonly BindableProperty DefaultPasswordProperty = BindableProperty.Create(nameof(DefaultPassword), typeof(string), typeof(AuthenticatedWebView), string.Empty); public string DefaultUsername { get => (string)GetValue(DefaultUsernameProperty); set => SetValue(DefaultUsernameProperty, value); } public string DefaultPassword { get => (string)GetValue(DefaultPasswordProperty); set => SetValue(DefaultPasswordProperty, value); } } }
Android平台自定义渲染器
using Android.App; using Android.Content; using Android.Webkit; using Android.Widget; using YourAppNamespace.Controls; using YourAppNamespace.Droid.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(AuthenticatedWebView), typeof(AuthenticatedWebViewRenderer))] namespace YourAppNamespace.Droid.Renderers { public class AuthenticatedWebViewRenderer : WebViewRenderer { public AuthenticatedWebViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control == null || e.NewElement == null) return; Control.SetWebViewClient(new AuthWebViewClient((AuthenticatedWebView)e.NewElement)); Control.Settings.JavaScriptEnabled = true; } private class AuthWebViewClient : WebViewClient { private readonly AuthenticatedWebView _authWebView; public AuthWebViewClient(AuthenticatedWebView webView) => _authWebView = webView; public override void OnReceivedHttpAuthRequest(Android.Webkit.WebView view, HttpAuthHandler handler, string host, string realm) { // 模式1:直接使用默认身份信息完成验证,无需弹窗 handler.Proceed(_authWebView.DefaultUsername, _authWebView.DefaultPassword); // 模式2:弹出原生弹窗让用户手动输入,注释上面一行,放开以下代码即可 /* var alertBuilder = new AlertDialog.Builder(view.Context); alertBuilder.SetTitle("身份验证"); var inflater = LayoutInflater.From(view.Context); var authLayout = inflater.Inflate(Resource.Layout.AuthDialog, null); var userInput = authLayout.FindViewById<EditText>(Resource.Id.et_username); var pwdInput = authLayout.FindViewById<EditText>(Resource.Id.et_password); alertBuilder.SetView(authLayout); alertBuilder.SetPositiveButton("确认", (s, args) => handler.Proceed(userInput.Text, pwdInput.Text)); alertBuilder.SetNegativeButton("取消", (s, args) => handler.Cancel()); alertBuilder.Show(); */ } } } }
iOS平台自定义渲染器
using Foundation; using UIKit; using WebKit; using YourAppNamespace.Controls; using YourAppNamespace.iOS.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(AuthenticatedWebView), typeof(AuthenticatedWebViewRenderer))] namespace YourAppNamespace.iOS.Renderers { public class AuthenticatedWebViewRenderer : WkWebViewRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); if (e.NewElement == null) return; NavigationDelegate = new AuthNavigationDelegate((AuthenticatedWebView)e.NewElement); } private class AuthNavigationDelegate : WKNavigationDelegate { private readonly AuthenticatedWebView _authWebView; public AuthNavigationDelegate(AuthenticatedWebView webView) => _authWebView = webView; public override void DidReceiveAuthenticationChallenge(WKWebView webView, NSUrlAuthenticationChallenge challenge, System.Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodHTTPBasic) { // 模式1:直接使用默认身份信息完成验证,无需弹窗 var credential = new NSUrlCredential(_authWebView.DefaultUsername, _authWebView.DefaultPassword, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); // 模式2:弹出原生弹窗让用户手动输入,注释上面两行,放开以下代码即可 /* var alert = UIAlertController.Create("身份验证", "请输入访问凭据", UIAlertControllerStyle.Alert); alert.AddTextField(tf => tf.Placeholder = "账号"); alert.AddTextField(tf => { tf.Placeholder = "密码"; tf.SecureTextEntry = true; }); alert.AddAction(UIAlertAction.Create("确认", UIAlertActionStyle.Default, _ => { var user = alert.TextFields[0].Text; var pwd = alert.TextFields[1].Text; var inputCred = new NSUrlCredential(user, pwd, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, inputCred); })); alert.AddAction(UIAlertAction.Create("取消", UIAlertActionStyle.Cancel, _ => { completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null); })); UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null); */ return; } completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, null); } } } }
页面调用示例
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:YourAppNamespace.Controls" x:Class="YourAppNamespace.WebDemoPage"> <controls:AuthenticatedWebView DefaultUsername="test_account" DefaultPassword="test_pwd123" Source="https://your-need-auth-target-url.com" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/> </ContentPage>
注意事项
- 代码中所有
YourAppNamespace需要替换为你项目的实际命名空间 - Android端如果使用手动输入弹窗模式,需要自行在Resources/layout下添加对应的AuthDialog布局文件
- 已废弃的UIWebView不兼容当前iOS代码,推荐所有iOS项目统一使用WkWebView
内容的提问来源于stack exchange,提问作者A Khan
相关产品推荐
相关产品推荐

