扩展 Microsoft.Owin.Security
微软在 OWIN 框架中对 OAuth 认证的支持非常好, 使用现有的 OWIN 中间件可以做到:
- 使用 Microsoft.Owin.Security.OAuth 搭建自己的 OAuth2 服务端, 没做过的可以参考这个简单教程: 使用 OWIN 搭建 OAuth2 服务器 ;
- 使用 Microsoft.Owin.Security.Facebook 连接 Facbook 认证, 让用户使用 Facebook 帐户来登录;
- 使用 Microsoft.Owin.Security.Google 连接 Google 认证, 让用户使用 Google 帐户登录;
- 使用 Microsoft.Owin.Security.MicrosoftAccount 连接 Microsoft 认证, 让用户使用 Microsoft 帐户登录;
- 使用 Microsoft.Owin.Security.Twitter 连接 Twitter 认证, 让用户使用 Twitter 帐户登录;
微软提供了这么多的 OAuth 认证中间件, 对天朝的墙内用户来说, 只能用三个字来概括“然并卵”。
要接入国内 腾讯微信 、新浪微博提供的 OAuth2 认证, 还是要根据现有的中间件 Microsoft.Owin.Security 进行二次开发, 上面微软提供的 Facebook、 Google 等实现可以作为参考。
先来简单回顾一下 OAuth2 的 认证流程 , 如下图所示:

直接和 OAuth2 认证服务器交互的步骤有:
- (A) 将用户代理(浏览器)重定向到认证服务器, 需要提供客户端凭据 (Client Identifier) , 并取得认证码 (Authorization Code) ;
- (D) 使用认证服务器返回的认证码 (Authorization Code) 获取访问凭据 (Access Token) ;
- (E) 根据访问凭据 (Access Token) 获取用户信息。
Microsoft.Owin.Security 对这些步骤提供了优秀的扩展支持, 扩展步骤如下:
1、 创建自定义的 OAuth2AuthenticationOptions ,并继承自 Microsoft.Owin.Security.AuthenticationOptions , 代码如下:
public class OAuth2AuthenticationOptions : AuthenticationOptions {
// Client App Identifier
public string AppId { get; set; }
// Client App Secret
public string AppSecret { get; set; }
// The authorize url
public string AuthorizationEndpoint { get; set; }
// Token url
public string TokenEndpoint { get; set; }
// User info url
public string UserInformationEndpoint { get; set; }
}
2、 创建一个自定义的 Owin 中间件 OAuth2AuthenticationMiddleware , 并继承自 Microsoft.Owin.Security.AuthenticationMiddleware :
public class GdepAuthenticationMiddleware :
AuthenticationMiddleware<GdepAuthenticationOptions> { protected override AuthenticationHandler<OAuth2AuthenticationOptions> CreateHandler() {
return new OAuth2AuthenticationHandler(httpClient, logger);
} }
重写的基类的 CreateHandler 非常重要, 整个 OAuth2 认证的过程都会在这个方法创建的 AuthenticationHandler 实例中完成。
3、 接下来就是最重要的部分, OAuth2AuthenticationHandler 的实现了, 先来看一下基类 AuthenticationHandler , 实现它需要实现下面的几个方法:
public abstract class AuthenticationHandler {
protected abstract Task<AuthenticationTicket> AuthenticateCoreAsync ();
protected virtual Task ApplyResponseChallengeAsync () { }
public virtual Task<bool> InvokeAsync () { }
}
接下来分别说明一下这几个方法的作用:
在 ApplyResponseChallengeAsync 方法中响应 HTTP 401 Unauthorized , 将用户重定向到认证服务器, 即实现上面的步骤 (A) , 示例代码如下:
var authorizationEndpoint = Options.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state); var redirectContext = new GdepApplyRedirectContext(Context, Options, properties, authorizationEndpoint);
Options.Provider.ApplyRedirect(redirectContext);
在 AuthenticateCoreAsync 方法中根据认证服务器返回的认证码 (Authorization Code) 来获取用户信息, 示例代码如下:
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath; var tokenRequest = new Dictionary<string, string> {
["grant_type"] = "authorization_code",
["code"] = code,
["redirect_uri"] = redirectUri,
["client_id"] = Options.AppId,
["client_secret"] = Options.AppSecret
};
var tokenResponse = await httpClient.PostAsync(
Options.TokenEndpoint,
new FormUrlEncodedContent(tokenRequest)
);
tokenResponse.EnsureSuccessStatusCode(); string json = await tokenResponse.Content.ReadAsStringAsync();
var form = JObject.Parse(json); var accessToken = form.Value<string>("access_token");
var expires = form.Value<string>("expires_in");
var tokenType = form.Value<string>("token_type");
var refreshToken = form.Value<string>("refresh_token"); string graphAddress = Options.UserInformationEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken);
if (Options.SendAppSecretProof) {
graphAddress += "&appsecret_proof=" + GenerateAppSecretProof(accessToken);
} var graphRequest = new HttpRequestMessage(HttpMethod.Get, graphAddress);
graphRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var graphResponse = await httpClient.SendAsync(graphRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
json = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(json);
在 InvokeReplyPathAsync 方法中用 SignInManager 登录, 然后返回给后续的应用程序 WebAPI 来处理, 示例代码如下:
var context = new GdepReturnEndpointContext(Context, ticker);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticker.Properties.RedirectUri; await Options.Provider.ReturnEndpoint(context); if (context.SignInAsAuthenticationType != null && context.Identity != null) {
var grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal)) {
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
到现在为止, 自定义的 OAuth2 认证中间件基本上就完成了, 代码量不算多, 如果有不清楚的地方, 可以参阅 katanaproject 的源代码。
扩展 Microsoft.Owin.Security的更多相关文章
- SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...
- Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端 目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Se ...
- 无法安装程序包“MIcrosoft.Owin.Security 2.0.2”。您正在尝试将此程序包安装到某个将“.NETFramework,Version=v4.0”作为目标的项目中。
在VS2010 MVC4项目中,安装NuGet程序包Microsoft.AspNet.SignalR时出现以下错误: 原因是安装的版本是Microsoft.AspNet.SignalR 2.0.2,要 ...
- OAuth Implementation for ASP.NET Web API using Microsoft Owin.
http://blog.geveo.com/OAuth-Implementation-for-WebAPI2 OAuth is an open standard for token based aut ...
- 无法解决“Microsoft.SharePoint.Security, Version=15.0.0.0,”与“Microsoft.SharePoint.Security, Version=14.0.0.0”之间的冲突
VisualStudio 2013创建控制台项目,.NetFramework选为4.5.生成目标平台:x64.然后添加对Microsoft.SharePoint.dll的引用. 生成项目时," ...
- Microsoft.Owin.Hosting 实现启动webapp.dll
Microsoft.Owin.Hosting 下面是 asp.net core 实现 using System;using System.Collections.Generic;using Syste ...
- Microsoft.SharePoint.Security的问题
请求“Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0 ...
- windows service承载的web api宿主搭建(Microsoft.Owin+service)
今天突然想起改良一下以前搭建的“windows service承载的web api”服务,以前也是直接引用的类库,没有使用nuget包,时隔几年应该很旧版本了吧.所以本次把需要nuget获取的包记录一 ...
- Microsoft.Owin 使用 文件服务
添加引用: <package id="Microsoft.Owin" version="4.0.1" targetFramework="net4 ...
随机推荐
- 2018-8-10-docfx-做一个和微软一样的文档平台
title author date CreateTime categories docfx 做一个和微软一样的文档平台 lindexi 2018-08-10 19:16:51 +0800 2018-2 ...
- 记录:vue结合springboot进行分页查询和按条件进行查询
界面: 主要代码: 搜索框: <el-form ref="searchForm" :inline="true" :model="searchMa ...
- [转]WPF命令集 Command
在我们日常的应用程序操作中,经常要处理各种各样的命令和进行相关的事件处理,比如需要复制.粘贴文本框中的内容;上网查看网页时,可能需要返回上一网页查看相应内容;而当我们播放视频和多媒体时,我们可能要调节 ...
- iftop实时监控网络流量
需要安装,linux自身不自带该命令 中间的<= =>这两个左右箭头,表示的是流量的方向. TX:发送流量 RX:接收流量 TOTAL:总流量 Cumm:运行iftop到目前时间的总流量 ...
- 关于set的unordered特性
关于set排序无序的问题,原因是set使用哈希表做内存索引. 详细介绍可见: https://stackoverflow.com/questions/12165200/order-of-unorder ...
- python登录aspx网站
1.安装模块 2.准备aspx登录页面 3.示例代码 #coding:utf-8 import re from bs4 import BeautifulSoup import gzip import ...
- bootstrap面包屑在ie8下显示重叠,鼠标点击显示效果正常
ie8下加载后的显示 点击之后的显示 主要是li标签宽度auto引起的,可以设置li标签的最小宽度 <ol class="breadcrumb"> <li id= ...
- nodejs package.json说明
{ "name": "test", //项目名称(必须),由小写英文字母.数字和下划线,不能含空格 "version": "1.0 ...
- numpy 常用工具函数 —— np.bincount/np.average
numpy 常用工具函数 —— np.bincount/np.average numpy 常用api(一) numpy 常用api(二) 一个函数提供 random_state 的关键字参数(keyw ...
- Leetcode98. Validate Binary Search Tree验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索 ...