【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务
前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似。

让用户通过客户端去获取自己的token,在根据这个token去获取资源。
本地登录凭据流
- 用户输入名称和密码到客户端。
- 客户端将这些凭据发送到授权服务器。
- 授权服务器验证凭据并返回访问令牌。
- 要访问受保护资源,客户端在HTTP请求的Authorization标头中包含访问令牌。
服务实现:
使用WebApi基于Microsoft.Owin.Security.OAuth实现,新建一个空为WebApi项目。
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web; namespace ApiThrottleDemo
{
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{ /// <summary>
/// 验证客户[client_id与client_secret验证]
/// </summary>
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
//http://localhost:48339/token
string client_id;
string client_secret;
context.TryGetFormCredentials(out client_id, out client_secret);
if (client_id == "zara" && client_secret == "123456")
{
context.Validated(client_id);
}
else
{
//context.Response.StatusCode = Convert.ToInt32(HttpStatusCode.OK);
context.SetError("invalid_client", "client is not valid");
}
return base.ValidateClientAuthentication(context);
} /// <summary>
/// 客户端授权[生成access token]
/// </summary>
public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
{ var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, "iphone"));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties() { AllowRefresh = true });
context.Validated(ticket);
return base.GrantClientCredentials(context);
} /// <summary>
/// 刷新Token[刷新refresh_token]
/// </summary>
public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
//enforce client binding of refresh token
if (context.Ticket == null || context.Ticket.Identity == null || !context.Ticket.Identity.IsAuthenticated)
{
context.SetError("invalid_grant", "Refresh token is not valid");
}
return base.GrantRefreshToken(context);
}
}
}
在此其中呢,需要继承OAuthAuthorizationServerProvider,并重写自己想重写的方法,其内部定义下图所示:

当然这还没完,我们还需要去配置应用程序。在Startup.cs,我们要开启BearerToken认证模式;该Provider属性指定了一个插入OWIN中间件的提供程序,并处理由中间件引发的事件。
以下是应用想要获取令牌时的基本流程:
要获取访问令牌,应用程序会向〜/ Token发送请求。
OAuth中间件调用GrantResourceOwnerCredentials提供程序。
提供程序调用ApplicationUserManager以验证凭据并创建声明标识。
如果成功,则提供程序会创建一个身份验证票证,用于生成令牌。
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
AuthenticationMode = AuthenticationMode.Active,
AllowInsecureHttp = true
});
其中AccessTokenExpireTimeSpan参数是token过期时间,AllowInsecureHttp 是否开启安全验证,TokenEndpointPath就是你获取token对于服务器的相对路径,那我们都知道用户只能访问我们的Api,那如何在api上去走Oauth呢?
客户端获取票据
在控制器种创建一个控制器,命名为:OAuth2Controller。
[RoutePrefix("api/v1/oauth2")]
public class OAuth2Controller : ApiController
{
[Authorize]
[Route("news")]
public async Task<IHttpActionResult> GetNewsAsync()
{
var authentication = HttpContext.Current.GetOwinContext().Authentication;
var ticket = authentication.AuthenticateAsync("Bearer").Result;
var claimsIdentity = User.Identity as ClaimsIdentity;
var data = claimsIdentity.Claims.Where(c => c.Type == "urn:oauth:scope").ToList();
var claims = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity).Claims;
return Ok(new { IsError = true, Msg = string.Empty, Data = Thread.CurrentPrincipal.Identity.Name + " It's about news !!! token expires: " + ticket.Properties.Dictionary.ToString() });
}
}
启用授权验证[WebApiConfig]
在ASP.NET Web API中启用Token验证,需要加上[Authorize]标记,并且配置默认启用验证不记名授权方式
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
服务端[/token]获取token需要三个参数,我们使用大家熟悉的PostMan去试一试吧,启动项目。

那我们不难看到,已经成功获取了access_token,至于这个token的值,只要你的client_id不同它就一定是不会相同的(实在不行你可以搞个GUID),那么我们再构建一个ajax去模拟的获取token吧。
做个简单的页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<input type="text" placeholder="client_id"/><br />
<input type="text" placeholder="client_secret"/><br />
<input type="text" placeholder="your_token"/><br />
<button>获取token</button>
</body>
<script>
$(function () {
$("button").click(function () {
$.ajax({
url: "http://localhost:58560/token",
type: "post",
data: "grant_type=client_credentials&client_id=zara&client_secret=123456",
success: function (res) {
console.log(res);
}
})
})
})
</script>
</html>
这是生成的token。

最后总结,你可以在ValidateClientAuthentication中进行身份判断,如果有这个身份,那么我就存储DB中,这样的话,类似于一个微信身份授权的功能基本上就是这样了。
【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务的更多相关文章
- Owin中间件搭建OAuth2.0认证授权服务体会
继两篇转载的Owin搭建OAuth 2.0的文章,使用Owin中间件搭建OAuth2.0认证授权服务器和理解OAuth 2.0之后,我想把最近整理的资料做一下总结. 前两篇主要是介绍概念和一个基本的D ...
- 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】
之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了.官方推 ...
- 使用Owin中间件搭建OAuth2.0认证授权服务器
前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OA ...
- Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务
API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...
- (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】
适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- 基于OWIN+DotNetOpenOAuth实现OAuth2.0
这几天时间一直在研究怎么实现自己的OAuth2服务器,对于太了解OAuth原理以及想自己从零开始实现的,我建议可以参考<Apress.Pro ASP.NET Web API Security&g ...
- Spring Cloud 微服务中搭建 OAuth2.0 认证授权服务
在使用 Spring Cloud 体系来构建微服务的过程中,用户请求是通过网关(ZUUL 或 Spring APIGateway)以 HTTP 协议来传输信息,API 网关将自己注册为 Eureka ...
随机推荐
- Docker 学习4 Docker容器虚拟化网络概述
一.docker 虚拟化网络概述 1.OVS: OpenVSwitch,不仅能模拟二层网络,还能模拟三层网络,或者VLAN,VXLAN,流控 SDN软件定义网络技术等. 2.overlay netwo ...
- 2018-2019-2 20165239其米仁增《网络对抗》Exp1 PC平台逆向破解
一.实验内容 1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码(0.5分) 2.掌握反汇编与十六进制编程器 (0.5分) 3.能正确修改机器指令改变程序执行流程(0.5分) 4.能 ...
- C语言第01次作业--顺序、分支结构
1.本章学习总结 1.1 思维导图 1.2本章学习体会及代码量学习体会 1.2.1学习体会 本周我学到了很多C语言中基础的结构和语法(见思维导图),能对一些生活中的简单问题对应编写程序解决一些这些简单 ...
- JavaWeb-SQL-Servlet-JSP学做购物系统——日志一
一.JDBCUtil 本人自半路出家学码代码以来,bug不断,一直不顺利.路漫漫.话不多说,上bug:T_T; 代码是这样的: 自定义的方法,插入一个sql语句:execUpdate(String s ...
- SDN网络虚拟化中有效协调的映射算法
来自论文An efficient and coordinated mapping algorithm in virtualized SDN networks,来自期刊<信息与电子工程前沿> ...
- Ecust OJ
1 #include <bits/stdc++.h> using namespace std ; struct bigInt { ] ; int size ; ; private : vo ...
- 机器学习——KMeans
导入类库 from sklearn.cluster import KMeans from sklearn.datasets import make_blobs import numpy as np i ...
- IntelliJ IDEA 2016.2 配置Tomcat 运行Web项目
1.可能会出现的问题 Run-->Edit Configurations 中点击"+"号没有tomcat server... 解决办法:File--->Setting- ...
- DIV滚动条滚动到指定位置(jquery的position()与offset()方法区别小记)
相对浏览器,将指定div滚到到指定位置,其用法如下 $("html,body").animate({scrollTop: $(obj).offset().top},speed); ...
- ajax经典面试题
1.什么是AJAX,为什么要使用Ajax(请谈一下你对Ajax的认识) 什么是ajax: AJAX是“Asynchronous JavaScript and XML”的缩写.他是指一种创建交互式网页应 ...