照猫画虎owin oauth for qq and sina
ms随vs2013推出了mvc5,mvc5自带的模板项目中引用了新的身份认证框架 ms identity。其中owin部分实现了google,facebook,twitter等国外常见的第三方用户。可惜国内没人用这些。
只能照猫画虎实现以下qq和sina的了
首先看ms自带的google和facebook的代码
每个类库里,有6个类一个接口,其中扩展类放在Owin命名空间下,是为了在startup中方便调用
看看startup中被注释掉的代码就知道了,都是UsexxxAuthentication。同理,希望可以有
app.UseQQAuthentication和app.UseSinaAuthentication
通过查看扩展方法,可以发现,最终调用了app.Use
对应的FacebookAuthenticationMiddleware和GoogleAuthenticationMiddleware才是owin相关的关键部分
XXXMiddleware是一个实现了OwinMiddleware的类(Middleware译为中间件),继承他,然后Use到app里,就可以在Invoke时去处理请求
不过我们不需要继承OwinMiddleware这么底层的类,因为有与身份认证相关的中间件基类了
public abstract class AuthenticationMiddleware<TOptions> : OwinMiddleware where TOptions : AuthenticationOptions
看此类的签名就知道,我们还需要一个Options类,应该去继承AuthenticationOptions类
看看微软给的。在options类里,一般都会有一些属性,去让使用者设定appid和appkey等信息,对oauth验证来说,基本就这两个是最重要的。
稍微需要注意一下的是
base(“Google”)中的google是写死传进去的,这个对应的是
这里的文字
而Caption对应的是
这里的文字(鼠标悬停出现的)
如果希望按钮的文字也由使用者提供,可以实现带参的构造
来看看最核心的中间件吧。
已google的为例,发现他并没有实现Invoke方法,那就应该是在基类里已经实现了。
反而是实现了一个CreateHandler方法
new了一个GoogleAuthenticationHandler返回
再看看facebook的
也一样。在对象浏览器里没发现这个Handler类啊。好在有各种反编译。
这个是个internal的类(最恨internal和sealed)
看看中间件类里,比较简单
1、构造函数就是给options赋一些默认值
2、创建Handler
3、私有方法,在构造中调用
没了
那核心明显从中间件转到了Handler
再看Handler之前,先看看其他的那几个类
XXXReturnEndpointContext实现ReturnEndpointContext,除了构造没别的
太简单了,咱也整个QQReturnEndpointContext和SinaReturnEndpointContext放着
再看IGoogleAuthenticationProvider和IFacebookAuthenticationProvider,都一样的
Task Authenticated(FacebookAuthenticatedContext context);
Task ReturnEndpoint(FacebookReturnEndpointContext context);
除了参数的类型不一样外,其他的都一样的。我们也写一个放着。
再看接口的实现,也一样的,代码不贴了。写两个放着。
到目前为止,我们有以下几个类
1、扩展方法来
2、Options类
3、中间件类
4、Handler类
5、ReturnEndpointContext类
6、Provider接口
7、Provider实现
还剩下一个XXXAuthenticatedContext类
看google和facebook的实现可以发现,只有属性,没有方法,属性就是记录以下用户id,用户名字acesskey等信息
我们可以先把类建好,具体属性需要什么根据对应的api再加。
OK,我们回来看核心的Handler类。
可以发现,他们都实现了基类的3个方法
1、
protected override Task ApplyResponseChallengeAsync()
2、
public override async Task<bool> InvokeAsync()
3、
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
先说第一个,他的作用就是方法第三方api,看看是否授权了
对应的qq地址是:
https://graph.qq.com/oauth2.0/authorize?client_id={0}&response_type=code&redirect_uri={1}
对应的sina地址是:
https://api.weibo.com/oauth2/authorize?client_id={0}&redirect_uri={1}&response_type=code&state={2}
在方法的最后,通过
this.Response.StatusCode = 302;
this.Response.Headers.Set("Location", url);
来设置浏览器跳转
在连接中,我们需要有一个state参数,这个参数由app生成,传给oauth,oauth在传回来,对比验证,state生成后,会自动保存到cookie里,这是基类帮我们做好的。
AuthenticationProperties properties = responseChallenge.Properties;
this.GenerateCorrelationId(properties);
var protector=this.Options.StateDataFormat.Protect(properties);
只需要3行代码,就可以生成一个state验证串,把这个字符串附加在连接后面传给oauth即可
oauth的回调地址,是定义在Options里的CallbackPath
在对应的Options类里可以看到地址为/signin-google和signin-facebook,我们自己的qq和sina自然可以定义成signin-qq和signin-sina
找遍项目,也没有发现signin-google这个controller或者页面什么的,那为什么这个地址可以访问呢,访问他又会干什么呢
来看第二个方法InvokeAsync()
已google为例
public override async Task<bool> InvokeAsync()
{
bool flag;
if (this.Options.CallbackPath.HasValue && this.Options.CallbackPath == this.Request.Path)
flag = await this.InvokeReturnPathAsync();
else
flag = false;
return flag;
}
在这里判断了,如果当前访问的路径是CallbackPath的路径,则去执行一些东西,下面的InvokeReturnPathAsync是一个protected方法
真正的逻辑在这个方法里
public async Task<bool> InvokeReturnPathAsync()
{
AuthenticationTicket model = await this.AuthenticateAsync();
bool flag;
if (model == null)
{
LoggerExtensions.WriteWarning(this._logger, "Invalid return state, unable to redirect.", new string[0]);
this.Response.StatusCode = 500;
flag = true;
}
else
{
GoogleReturnEndpointContext context = new GoogleReturnEndpointContext(this.Context, model);
context.SignInAsAuthenticationType = this.Options.SignInAsAuthenticationType;
context.RedirectUri = model.Properties.RedirectUri;
model.Properties.RedirectUri = (string) null;
await this.Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null && context.Identity != null)
{
ClaimsIdentity claimsIdentity = context.Identity;
if (!string.Equals(claimsIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
claimsIdentity = new ClaimsIdentity(claimsIdentity.Claims, context.SignInAsAuthenticationType, claimsIdentity.NameClaimType, claimsIdentity.RoleClaimType);
this.Context.Authentication.SignIn(context.Properties, new ClaimsIdentity[1]
{
claimsIdentity
});
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
if (context.Identity == null)
context.RedirectUri = WebUtilities.AddQueryString(context.RedirectUri, "error", "access_denied");
this.Response.Redirect(context.RedirectUri);
context.RequestCompleted();
}
flag = context.IsRequestCompleted;
}
return flag;
}
(google和facebook的,除了类名不一样,其他的都一样,copy一下就可以了。)
所以,当回调到signin-google这个地址的时候,是可以正常访问的。
最后来看AuthenticateCoreAsync
首先是检查回调地址的参数,如果没有state,就返回null了。
然后是this.ValidateCorrelationId(properties, this._logger)通过这个方法,来与cookie里保存的state对比,如果不对,也返回null了
剩下的就是回调正确,改进行下一步了。
最终的目的是要返回一个AuthenticationTicketpublic AuthenticationTicket(ClaimsIdentity identity, AuthenticationProperties properties)需要2个参数,其中properties我们已经有了(在前面就可以构造出来,具体可看源码)
这里主要是需要构造一个ClaimsIdentity
ClaimsIdentity identity = new ClaimsIdentity(this.Options.AuthenticationType);
理论上new一个就ok,并且,如果仅仅是这么写,他也能过去的,会进入下一步,但是到下一步的时候,有时候会包nullreference异常。
这里应该传入当前用户id和名字
identity.AddClaim(new Claim(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier,
“id”, "http://www.w3.org/2001/XMLSchema#string", this.Options.AuthenticationType));
identity.AddClaim(new Claim(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name,
“名字”, "http://www.w3.org/2001/XMLSchema#string", this.Options.AuthenticationType));
至少需要id,第一次用第三方登录进来时,他会让你在本地注册
此时AspNetUserLogins表中会加入一条数据
联合主键,UserId对应AspNetUsers表中的主键
LoginProvider是你所使用的第三方登录的标识就是Options调用base(“xxxx”)这里传进去的那个值
而最后一个ProviderKey,则是你这个第三方登录返回的用户id,比如你用sina的登陆,这里记录的应该是你sina的那个id
qq的,就是qq记录你的那个id(qq的叫open id)
具体这几个表是如何存储,是和MS Identity有关的。
这个id和名字这么获得?
当然是调用oauth的api了。
目前,我们只是调用了授权服务,回调的参数里有authorization code,我们需要拿这个authorization code 去请求access token,再拿access token 去请求当前的人的昵称和id等其他信息
简单实现了一下
https://github.com/czcz1024/OwinQQ
包括qq和sina的,因为不想引入其他的类库,所以id,名字还包括access token等都是拿正则截取的,如果你觉得不爽,可以自己做json转换
照猫画虎owin oauth for qq and sina的更多相关文章
- ASP.NET OWIN OAuth:遇到的2个refresh token问题
之前写过2篇关于refresh token的生成与持久化的博文:1)Web API与OAuth:既生access token,何生refresh token:2)ASP.NET OWIN OAuth: ...
- ASP.NET OWIN OAuth:refresh token的持久化
在前一篇博文中,我们初步地了解了refresh token的用途——它是用于刷新access token的一种token,并且用简单的示例代码体验了一下获取refresh token并且用它刷新acc ...
- ASP.NET Web API与Owin OAuth:调用与用户相关的Web API
在前一篇博文中,我们通过以 OAuth 的 Client Credential Grant 授权方式(只验证调用客户端,不验证登录用户)拿到的 Access Token ,成功调用了与用户无关的 We ...
- 在ASP.NET Web API 2中使用Owin OAuth 刷新令牌(示例代码)
在上篇文章介绍了Web Api中使用令牌进行授权的后端实现方法,基于WebApi2和OWIN OAuth实现了获取access token,使用token访问需授权的资源信息.本文将介绍在Web Ap ...
- owin Oauth
原文:http://www.cnblogs.com/richieyang/p/4918819.html 一.什么是OAuth OAuth是一个关于授权(Authorization)的开放网络标准,目前 ...
- ASP.NET Web API与Owin OAuth:使用Access Toke调用受保护的API
在前一篇博文中,我们使用OAuth的Client Credential Grant授权方式,在服务端通过CNBlogsAuthorizationServerProvider(Authorization ...
- 在ASP.NET中基于Owin OAuth使用Client Credentials Grant授权发放Token
OAuth真是一个复杂的东东,即使你把OAuth规范倒背如流,在具体实现时也会无从下手.因此,Microsoft.Owin.Security.OAuth应运而生(它的实现代码在Katana项目中),帮 ...
- 在WebApi中基于Owin OAuth使用授权发放Token
如何基于Microsoft.Owin.Security.OAuth,使用Client Credentials Grant授权方式给客户端发放access token? Client Credentia ...
- WebApi Owin OAuth
Microsoft.Owin.Host.SystemWeb Owin Microsoft.Owin Microsoft.Owin.Diagnostics Owin Micros ...
随机推荐
- uwp ListView列表滑动特效
在看过一篇文章 WPF自定义控件之列表滑动特效 PowerListBox http://www.cnblogs.com/ShenNan/p/4993374.html#3619585 实现了滑动的特效 ...
- ACTGame项目
项目地址:https://github.com/alonecat06/ACTGame游戏地址:http://pan.baidu.com/s/1hqD3IYw 项目是一个自制单机动作游戏demo,方向是 ...
- .net下使用最小堆实现TopN算法
测试代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...
- zoj4019 Schrödinger's Knapsack(dp)
题意:有两种物品分别为n,m个,每种物品对应价值k1,k2.有一个容量为c的背包,每次将一个物品放入背包所获取的价值为k1/k2*放入物品后的剩余体积.求问所获取的最大价值. 整体来看,优先放入体积较 ...
- OC 中的属性
自动合成 (autosynthesis) @property 语法,会做下面两件事情 自动生成存取方法 由编译器生成,编辑器里不会看到这些方法. 向类中添加适当类型的实例变量 在属性前加下划线,作为实 ...
- 2014年10月Android面试总结
最近打算跳槽,所以到外面逛了一圈,发现外面的世界还是比较精彩的,同时也认识了自己的一些不足,以及作为一个Android开发者,自己后面需要掌握的东西做一下列举. 先介绍下本人的工作经历吧,本人11年7 ...
- 下载一个vue项目执行npm install 后运行项目npm run dev后出错 - 问题解决
在SVN上拉下来一个vue项目,上面没有提交项目里面的node_modules文件夹,所以要自己执行 npm install 安装,但安装完后运行项目后却报错了: $ npm run dev > ...
- 【BZOJ2300】【HAOI2011】防线修建
题目大意:给你m+3个点,有q个操作,每次要么询问当前点集构所构成的上凸壳总长度,要么在当前点集中删除一个点. 这题是吼题啊!!! 刚开始想着如何正常地做,考虑过用线段树维护一个区间内的凸包,发现并不 ...
- OS之进程管理 --- 死锁
什么是死锁 在正常操作模式下,进程按如下顺序来使用资源: 申请:进程请求资源 使用:进程对资源进行操作 释放:进程释放资源 当一组进程中的每一个进程度在等待一个事件,而这事件只能有一组进程的另一个进程 ...
- https数字证书交换过程介绍
文章转自:https://www.2cto.com/kf/201804/739010.html,感谢原作者的辛苦整理,讲解的很清楚,谢谢. [https数字证书交换过程介绍] 注意:该问的背景用到了非 ...