【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社区也发布过一篇详细的文章介绍多语言工 ...
随机推荐
- Java面试——线程池
1.类比介绍 假如有一个工厂,工厂里面有10个工人,每个工人同时只能做一件任务. 因此只要当10个工人中有工人是空闲的,来了任务就分配给空闲的工人做: 当10个工人都有任务在做时,如果还来了任务,就把 ...
- 《从零玩转python+人工智能-3》网易云课堂王顺子
#1.145——152节课25章——面向对象三大特性小案例 class Animal: def __init__(self,name,age=1): self.name = name self.age ...
- leetcode139
class Solution { public: bool wordBreak(string s, vector<string> wordDict) { vector<, false ...
- Linux命令:cd
语法 cd [-L|[-P [-e]]] [dir]改变shell当前工作目录.仅对执行命令所在的shell有效. 参数 -L 按符号链接进入目录. -P 按物理链接进入目录 -e 如果指 ...
- install mysql from source and troubleshooting example
I tried to install MySQL 5.7 from source file and upgrading previous MySQL version to the lastest 5. ...
- 源码解析之AQS源码解析
要理解Lock首先要理解AQS,而要理解并发类最好的方法是先理解其并发控制量不同值的含义以及该类运作流程,然后配合一步步看源码.该类有一个重要的控制量是WaitStates,节点的状态值. /** w ...
- Java ArrayList调用构造方法传入"容量size"不生效,如何初始化List容量size
创建一个ArrayList对象,传入整型参数 @Test public void arrayListConstructor(){ ArrayList<Object> objects = n ...
- linux下redis4.0.2集群部署(利用原生命令)
一.部署架构如下 每台服务器准备2个节点,一主一从,主节点为另外两台其中一台的主,从节点为另外两台其中一台的从. 二.准备6个节点配置文件 在172.28.18.75上操作 cd /etc/redis ...
- oslo_messaging与rabbitmq
oslo_messaing通过kombu与rabbitmq建立channel连接,向rabbitmq中发送数据 在oslo_messaging/_drivers/impl_rabbit.py中,初始化 ...
- Pushlet实现后台信息推送(一)
Pushlet是使用较多的后台向前台推送信息的工具.前台订阅某个感兴趣的事件joinListen,触发后台的Pushlet的servlet,为该请求会话建立session,默认这个sessionID是 ...