【UWP】手动实现 WebAuthenticationBroker
在 UWP 中,如果要进行 OAuth 授权,那很大概率是会用上 WebAuthenticationBroker 这个类的,例如微博授权这种。
在一般情况下来说,WebAuthenticationBroker 是足够用的了,但是,如果你是碰上 Github 授权的话,那么就会碰到这样的情况:

蹦出一大个警告,让人看上去相当不爽。归根的原因是 WebAuthenticationBroker 使用的是 IE 内核,这个我们可以通过 https://www.whatismybrowser.com/ 验证。

连 Edge 内核都不是,不给力啊,老湿。
那么有没有办法把 WebAuthenticationBroker 换成 Edge 内核呢?简单的办法是没有的了,但我们还有 WebView,WebView 是使用 Edge 内核的,可以通过 WebView 来手动实现我们自己的 WebAuthenticationBroker。
参考 WebAuthenticationBroker 类的 AuthenticateAsync,编写如下代码:
public static class MyWebAuthenticationBroker
{
public static Task<MyWebAuthenticationResult> AuthenticateAsync(Uri requestUri, Uri callbackUri)
{
throw new NotImplementedException();
}
}
WebAuthenticationBroker 的 AuthenticateAsync 这个方法有 3 个参数,但第一个参数并不是很常用,所以这里就只使用后面的两个参数了。另外因为 WebAuthenticationResult 没有公共构造函数,所以定义一个 MyWebAuthenticationResult 来代替。
public class MyWebAuthenticationResult
{
public string ResponseData { get; internal set; } public uint ResponseErrorDetail { get; internal set; } public WebAuthenticationStatus ResponseStatus { get; internal set; }
}
接下来就是如何实现的问题。这里我们可以使用一个 ContentDialog 套 WebView 的方式。
在项目添加一个内容对话框(这里我叫 AuthorizationDialog),并编写如下代码:
<ContentDialog x:Class="WebAuthenticationBrokerDemo.AuthorizationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="正在连接到服务"
CloseButtonText="取消"
FullSizeDesired="True"
mc:Ignorable="d">
<ContentDialog.Resources>
<ResourceDictionary>
<x:Double x:Key="ContentDialogMinWidth">800</x:Double>
</ResourceDictionary>
</ContentDialog.Resources>
<Grid>
<WebView x:Name="WebView"
NavigationFailed="WebView_NavigationFailed"
NavigationStarting="WebView_NavigationStarting" />
</Grid>
</ContentDialog>
设置 FullSizeDesired 使高度占满窗口,资源字典中覆盖默认的对话框宽度。WebView 则订阅 Starting 和 Failed 事件。编写后台 cs 代码:
public sealed partial class AuthorizationDialog
{
private readonly Uri _callbackUri; public AuthorizationDialog(Uri requestUri, Uri callbackUri)
{
if (requestUri == null)
{
throw new ArgumentNullException(nameof(requestUri));
}
if (callbackUri == null)
{
throw new ArgumentNullException(nameof(callbackUri));
} _callbackUri = callbackUri; InitializeComponent(); WebView.Source = requestUri;
} public Uri ResponseUri { get; private set; } public WebAuthenticationStatus Result { get; private set; } = WebAuthenticationStatus.UserCancel; public WebErrorStatus WebErrorStatus { get; private set; } private bool CheckUri(Uri uri)
{
if (uri.Host == _callbackUri.Host)
{
Result = WebAuthenticationStatus.Success;
ResponseUri = uri;
return true;
} return false;
} private void WebView_NavigationFailed(object sender, WebViewNavigationFailedEventArgs e)
{
if (CheckUri(e.Uri))
{
Hide();
return;
} Result = WebAuthenticationStatus.ErrorHttp;
ResponseUri = e.Uri;
WebErrorStatus = e.WebErrorStatus;
Hide();
} private void WebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
if (CheckUri(args.Uri))
{
Hide();
}
}
}
可以通过 Hide 方法来关闭对话框。需要注意的是 Failed 的时候需要先检查一次,因为可能 callback 的地址是无法访问的。
接下来可以补完一开始的 AuthenticateAsync 方法了。
public static class MyWebAuthenticationBroker
{
public static async Task<MyWebAuthenticationResult> AuthenticateAsync(Uri requestUri, Uri callbackUri)
{
var authorizationDialog = new AuthorizationDialog(requestUri, callbackUri);
await authorizationDialog.ShowAsync();
if (authorizationDialog.Result == WebAuthenticationStatus.UserCancel)
{
return new MyWebAuthenticationResult
{
ResponseStatus = WebAuthenticationStatus.UserCancel
};
}
else if (authorizationDialog.Result == WebAuthenticationStatus.Success)
{
return new MyWebAuthenticationResult
{
ResponseStatus = WebAuthenticationStatus.Success,
ResponseData = authorizationDialog.ResponseUri.OriginalString
};
}
else
{
return new MyWebAuthenticationResult
{
ResponseStatus = WebAuthenticationStatus.ErrorHttp,
ResponseData = authorizationDialog.ResponseUri.OriginalString,
ResponseErrorDetail = (uint)authorizationDialog.WebErrorStatus
};
}
}
}
那么现在我们再去连 Github 之类的授权就不会有警告了,因为内核已经换成了 Edge。

而且因为是使用 WebView,所以还能再进行一些定制化的操作,例如执行 JavaScript,获取 Cookie 之类的。
【UWP】手动实现 WebAuthenticationBroker的更多相关文章
- MVVM框架从WPF移植到UWP遇到的问题和解决方法
MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...
- UWP开发必备:常用数据列表控件汇总比较
今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...
- UWP开发之Template10实践二:拍照功能你合理使用了吗?(TempState临时目录问题)
最近在忙Asp.Net MVC开发一直没空更新UWP这块,不过有时间的话还是需要将自己的经验和大家分享下,以求共同进步. 在上章[UWP开发之Template10实践:本地文件与照相机文件操作的MVV ...
- Win10 UWP开发系列——开源控件库:UWPCommunityToolkit
在开发应用的过程中,不可避免的会使用第三方类库.之前用过一个WinRTXamlToolkit.UWP,现在微软官方发布了一个新的开源控件库—— UWPCommunityToolkit 项目代码托管在G ...
- 【开源】知乎日报UWP 更新
说明 大概十天之前我更新了一次APP,后来又仔细看了一下Store里的评论,发现还有几个地方没有改过来.于是前天晚上抽时间改了一下,顺便完善了一下UI体验. 没有看前面文章的童鞋可以看一下下面的链接: ...
- 【完全开源】知乎日报UWP版:增加Live磁贴、Badge、以及Toast通知
目录 说明 实现方法 APP生命期 后台任务 说明 之前网上有人建议增加磁贴(tile).徽章(badge)功能.利用周末的时间,将这两个功能添加上去了.如果将磁贴固定到开始屏幕,磁贴就会循环播放首页 ...
- Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App
安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...
- UWP中重用C/C++代码时踩过的一些坑
标题中提到的UWP,主要是指用C#来写UWP的主工程,开发过程中可能需要调用C/C++实现的库. 为什么需要调用C/C++的库呢,举个例子,开源库OpenSSL实现了许多加密算法,稳定快速,我们想在应 ...
- Win10 UWP 开发系列:使用多语言工具包让应用支持多语言
之前我在一篇blog中写过如何使用多语言工具包,见http://www.cnblogs.com/yanxiaodi/p/3800767.html 在WinEcos社区也发布过一篇详细的文章介绍多语言工 ...
随机推荐
- (9/24) 图片跳坑大战--css分离与图片路径处理
前言: 在上一节当中,我们把小图片打包成Base64格式(打包到了js当中).我们也算是对webpack对图片的打包有个基本了解. 本节我们准备把css从JavasScript代码中分离出来,这会遇到 ...
- spring jdbc学习1
1.queryForObject - 其中的 RowMapper 指定如何去映射结果集的行, 常用的实现类为 BeanPropertyRowMapper - 使用 SQL 中列的别名完成列名和类的属性 ...
- 003之MFCSocket异步编程(指针机制)
002篇是采用传统方式创建,不适应动态的网络环境,服务器为客户端保留着断开连接时的套接字,不够灵活.而采用指针机制不仅可以更加灵活性,而且能使代码更集中,更具有条理性.将其转变成指针机制.功能及运行保 ...
- XSLT 创建CDATA节点
创建文本结点 (1)直接写入文本: text1 (2)通过<xsl:text>创建文本结点: <xsl:text>text2</xsl:text> (3)通过< ...
- 基于PaddlePaddle的语义匹配模型DAM,让聊天机器人实现完美回复 |
来源商业新知网,原标题:让聊天机器人完美回复 | 基于PaddlePaddle的语义匹配模型DAM 语义匹配 语义匹配是NLP的一项重要应用.无论是问答系统.对话系统还是智能客服,都可以认为是问题和回 ...
- ubuntu 从零安装tf-serving环境和opencv
参考官网:https://www.tensorflow.org/serving/setup 首先是安装gprc: pip install grpcio 然后发现没有安装pip,报错:sudo: pip ...
- python入门(五):切片列表元祖字典
1.切片 针对序列,使用切片可以获得我们想要的内容 序列:字符串.列表.元祖 特点:可以使用坐标获取某一个值.坐标是从0开始算 >>> s="0123456789" ...
- html2canvas
最近公司有个需求,实现html 页面元素转为png图像,这边用了html2canvas来实现.,这里记录一下,避免以后忘了~~ 官网链接: http://html2canvas.hertzen.com ...
- web服务,下载https链接的文件,提示javax.net.ssl.SSLKeyException: RSA premaster secret error
问题: 在服务器上,下载https的链接文件,报错javax.net.ssl.SSLKeyException: RSA premaster secret error 在本地运行的时候没报错,但是在 ...
- 【前言】Go语言开坑
很早之前就已经听过Go语言的大名,今天终于要开坑研究Go了,来吧看看<Go语言从入门到入坟>. [Go语言学习目录] 1. Go安装 2. Go变量(Variables) 3. Go语言基 ...