【干货】基于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 ...
随机推荐
- 关于<服务器>定义
定义: 服务器,也称伺服器,是提供计算服务的设备.由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力. 服务器的构成:包括处理器.硬盘.内存.系统总线等,和 ...
- Linux-day1-上课笔记
命令的组成 命令关键字 [选项] [参数] 注意: 1. 通常情况下 选项- --连接 ls -l /etc 2. - 选项和选项之间是可以合并的 ls -ld /etc ls 罗列文件 常见的选 ...
- Alpha冲刺(2/10)——2019.4.24
作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 ...
- MFC学习RepositionBars
学习过程中用到了就找了下资料 https://blog.csdn.net/u012372584/article/details/50718968
- Django“少折腾”
1.Django中文语言.时区 修改项目setting文件 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'
- iOS异常捕获和处理
2013年4月份整理的代码,仅作记录: //先宏定义 //发布和未发布状态的日志切换 #ifdef DEBUG //异常栈开关 #define STACK_KEY YES ...
- JAVA基础复习与总结<四> 抽象类与接口
抽象类(Abstract Class) 是一种模版模式.抽象类为所有子类提供了一个通用模版,子类可以在这个模版基础上进行扩展.通过抽象类,可以避免子类设计的随意性.通过抽象类,我们就可以做到严格限制子 ...
- 记一次非常规方法对接硬件设备(Grason Stadler GSI 61)
Grason Stadler GSI 61 电测听设备 (写下设备的名字, 希望别人遇坑可以搜到) 对接说明 设备厂家提供自带的软件,但是没有找到接口说明.我们需要获取设备发送过来的数据. 厂家提供的 ...
- 批量删除Excel里面的换行符
关于批量删除excel里面的换行符,应该说写程序的遇上excel大体都会有这么个问题,在解决这个问题前,我的解决办法是把excel 的数据全部复制到txt里面, 因为操作txt比操作excel更为简单 ...
- [LeetCode] New 21 Game 新二十一点游戏
Alice plays the following game, loosely based on the card game "21". Alice starts with 0 p ...