前言:采用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. 结对开发项目--石家庄地铁web版

    一.功能要求 1.数据库设计:将石家庄地铁线路图的各个线路,各个站点,换乘信息等用数据库的形式保存起来,应该保存的信息有 {线路号,线路的各个站名,车站的换乘信息}. 2.站点查询:用户可以输入任一一 ...

  2. 代码调用t.cn接口生成短址

    新浪短网址接口的稳定性和跳转速度还是很给力的,现给出其API说明. 该接口支持两种返回格式:xml和json 对应的URL请求地址为: xml:http://api.t.sina.com.cn/sho ...

  3. Markdown初使用

    Markdown是一种纯文本格式的标记语言.通过简单的标记语法,它可以使普通文本内容具有一定的格式. 相比WYSIWYG编辑器 优点:1.因为是纯文本,所以只要支持Markdown的地方都能获得一样的 ...

  4. Android全平台书籍

    <Android Database Programming>:全书研究Android平台下的数据库技术. <Android Application Programming with ...

  5. APM和PIX飞控日志分析入门贴

    我们在飞行中,经常会碰到各种各样的问题,经常有模友很纳闷,为什么我的飞机会这样那样的问题,为什么我的飞机会炸机,各种问题得不到答案是一件非常不爽的问题,在APM和PIX飞控中,都有记录我们整个飞行过程 ...

  6. python爬取珞珈1号卫星数据

    首先登录珞珈一号数据系统查询想要的数据 利用浏览器审查元素获取包含下载信息的源码 将最右侧的table相关的网页源码copy到剪切板备用 利用python下载数据 ## utf-8 import re ...

  7. VMware手动添加centos7硬盘图文操作及分区超详细

    先设置虚拟机 启动的虚拟机,新关机再设置 1.选择指定虚拟机,点击硬盘 2.虚拟机设置,点击左下角“添加” 3.硬件类型选择硬盘,点击下一步 4.添加硬件向导默认就行,下一步 5.选择磁盘,默认选中, ...

  8. 匿名函数 javascript

    匿名函数: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  9. javascript 变量的引入、变量的声明、变量的初始化

    变量的引入及声明和初始化: 变量: 操作的数据都是在内存中操作 Js中存储数据使用变量的方式(名称,值--->数据) Js中声明变量都用var--->存储数据,数据应该有对应的数据类型 存 ...

  10. iOS 开发中keyChain的使用

    我们开发中很多数据都是直接存储到本地沙盒中的,这样当应用程序被卸载后,本地的数据都会被删除.如果我们不想让数据在卸载程序的时候丢失,我们可以用KeyChain来存储我们想要的数据.苹果提供了原生的一套 ...