前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似。

让用户通过客户端去获取自己的token,在根据这个token去获取资源。

本地登录凭据流

  1. 用户输入名称和密码到客户端。
  2. 客户端将这些凭据发送到授权服务器。
  3. 授权服务器验证凭据并返回访问令牌。
  4. 要访问受保护资源,客户端在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进行客户端授权服务的更多相关文章

  1. Owin中间件搭建OAuth2.0认证授权服务体会

    继两篇转载的Owin搭建OAuth 2.0的文章,使用Owin中间件搭建OAuth2.0认证授权服务器和理解OAuth 2.0之后,我想把最近整理的资料做一下总结. 前两篇主要是介绍概念和一个基本的D ...

  2. 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】

    之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了.官方推 ...

  3. 使用Owin中间件搭建OAuth2.0认证授权服务器

    前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OA ...

  4. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  5. (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  6. 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】

    适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...

  7. 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  8. 基于OWIN+DotNetOpenOAuth实现OAuth2.0

    这几天时间一直在研究怎么实现自己的OAuth2服务器,对于太了解OAuth原理以及想自己从零开始实现的,我建议可以参考<Apress.Pro ASP.NET Web API Security&g ...

  9. Spring Cloud 微服务中搭建 OAuth2.0 认证授权服务

    在使用 Spring Cloud 体系来构建微服务的过程中,用户请求是通过网关(ZUUL 或 Spring APIGateway)以 HTTP 协议来传输信息,API 网关将自己注册为 Eureka ...

随机推荐

  1. vue中使用postMessage进行跨越传值

    想在“当前位置”获取子页面的title属性,但是main页面和子页面在不同的端口上,直接获取会出现: “Blocked a frame with origin from accessing a cro ...

  2. Python爬虫技术(从网页获取图片)+HierarchicalClustering层次聚类算法,实现自动从网页获取图片然后根据图片色调自动分类—Jason niu

    网上教程太啰嗦,本人最讨厌一大堆没用的废话,直接上,就是干! 网络爬虫?非监督学习? 只有两步,只有两个步骤? Are you kidding me? Are you ok? 来吧,follow me ...

  3. 利用 SQL Server Audit 审核哪些用户添加删除更新SQL Agent Job

    有的时候我们需要下放权限给不用的用户,让他们自己能管理一部分SQL Agent Job,此时需要详细记录谁在什么时间修改了Job 甚至删除了Job, 我们可以使用SQL Server 的Audit帮助 ...

  4. 洛谷.5300.[GXOI/GZOI2019]与或和(单调栈)

    LOJ BZOJ 洛谷 想了一个奇葩的单调栈,算的时候要在中间取\(\min\),感觉不靠谱不写了=-= 调了十分钟发现输出没取模=v= BZOJ好逗逼啊 题面连pdf都不挂了 哈哈哈哈 枚举每一位. ...

  5. Python的使用方法

    1 安装turtle Python2安装命令: pip install turtule Python3安装命令: pip3 install turtle 因为turtle库主要是在Python2中使用 ...

  6. 05解决flask循环引用的问题

    1, 什么是循环引用问题?为什么会导致循环引用? 1.1先讲是什么? 主文件中class类过多会导致主文件冗余,如下图,所以我们单独给class类一个文件,然后再引用它. 1.2再讲为什么? 主文件为 ...

  7. Makefile自学

    MakeFile的规则 如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接. 如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序. 如果这个工程的头文件被改变了, ...

  8. emoji 表情: MySQL如何支持 emoji 表情

    https://www.cnblogs.com/jentary/p/6655471.html 修改数据库字符集: ALTER DATABASE database_name CHARACTER SET ...

  9. 《JavaScript高级程序设计(第3版)》阅读总结记录第二章之在HTML中使用JavaScript

    本章目录: 2.1 <script> 元素 2.1.1 标签的位置 2.1.2 延迟脚本 2.1.3 异步脚本 2.1.4 在XHTML 中的用法 2.1.5 不推荐使用的语法 2.2 嵌 ...

  10. Android中RadioGroup的初始化和简单的使用

    一简介: RadioGroup作为一个单选按钮组,可以设置为性别选择男或则女,地址选择等等,作为一个android入门级选手,就简单的说一下RadioGroup组中RadioButton的布局和初始化 ...