ASP.NET Core 中基于 API Key 对私有 Web API 进行保护
这两天遇到一个应用场景,需要对内网调用的部分 web api 进行安全保护,只允许请求头账户包含指定 key 的客户端进行调用。在网上找到一篇英文博文 ASP.NET Core - Protect your API with API Keys,该文中的代码完美基于 ASP.NET Core 内置的鉴权(Authentication) 与授权(Authorization)机制解决了这个问题,于是站在巨人的肩上自己实现了一遍,在这篇随笔中做个记录。
ASP.NET Core Authentication 与 Authorization 实现的开源代码在 https://github.com/aspnet/AspNetCore/tree/master/src/Security 。
使用 API Key 对私有 Web API 进行保护,实际就是通过自定义的 AuthenticationHandler 对 ASP.NET Core Authentication 的鉴权能力进行扩展,具体实现分4步。
1)实现配角(配置选项)ApiKeyAuthenticationOptions
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultScheme = "ApiKey";
public string Scheme { get; set; } = DefaultScheme;
public string AuthenticationType { get; set; } = DefaultScheme;
}
这里的示例程序很简单,选项只用于定义 DefaultScheme 。
2)实现主角 ApiKeyAuthenticationHandler
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
private const string HEADER_NAME = "X-Api-Key";
private readonly (string Owner, string Key)[] _apiKeys = new[] { ("test", "xxx123yyy456zzz") };
private readonly ApiKeyAuthenticationOptions _options;
public ApiKeyAuthenticationHandler(
IOptionsMonitor<ApiKeyAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder Encoder,
ISystemClock clock) : base(options, logger, Encoder, clock)
{
_options = options.CurrentValue;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var providedApiKey = Context.Request.Headers[HEADER_NAME].FirstOrDefault();
if (string.IsNullOrWhiteSpace(providedApiKey))
{
return AuthenticateResult.NoResult();
}
var apiKey = _apiKeys.FirstOrDefault(k => k.Key == providedApiKey);
if (apiKey != default)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, apiKey.Owner)
};
var identity = new ClaimsIdentity(claims, authenticationType: _options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
var ticket = new AuthenticationTicket(principal, authenticationScheme: _options.Scheme);
await Task.CompletedTask;
return AuthenticateResult.Success(ticket);
}
return AuthenticateResult.Fail("Invalid API Key provided.");
}
}
在 override 方法 HandleAuthenticateAsync 中实现基于 API Key 对私有 Web API 进行保护的鉴权逻辑,根据客户端请求头进行验证,如果是合法请求,就发一个 ticket 。有了这张门票, 如果只要有门票就能通过(比如加了[Authorize]声明), 没有其他授权要求,Authorization 就会直接放行。
3)实现跑龙套的 AuthenticationBuilderExtensions 扩展方法
public static class AuthenticationBuilderExtensions
{
public static AuthenticationBuilder AddApiKeySupport(this AuthenticationBuilder authenticationBuilder)
{
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(
ApiKeyAuthenticationOptions.DefaultScheme,
options => { });
}
public static AuthenticationBuilder AddApiKeySupport(this AuthenticationBuilder authenticationBuilder,
Action<ApiKeyAuthenticationOptions> options)
{
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(
ApiKeyAuthenticationOptions.DefaultScheme,
options);
}
}
这个扩展方法只是为了方便在 Startup 中添加 ApiKeyAuthenticationHandler 。
4)开始演戏
Startup.ConfigureServices 中配置 Authentication
services.AddAuthentication(options =>
{
options.DefaultScheme = ApiKeyAuthenticationOptions.DefaultScheme;
options.DefaultChallengeScheme = ApiKeyAuthenticationOptions.DefaultScheme;
}).AddApiKeySupport();
Startup.Configure 中添加 Authentication 与 Authorization 中间件(注:一定要放在 app.UseRouting 之后)
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
对需要保护的 web api 添加 [Authorize] 声明
[Authorize]
public async Task<bool> ProtectedAction()
{
//...
}
搞定。
ASP.NET Core 中基于 API Key 对私有 Web API 进行保护的更多相关文章
- 【翻译】在Visual Studio中使用Asp.Net Core MVC创建你的第一个Web API应用(一)
HTTP is not just for serving up web pages. It's also a powerful platform for building APIs that expo ...
- [转]【翻译】在Visual Studio中使用Asp.Net Core MVC创建你的第一个Web API应用(一)
本文转自:https://www.cnblogs.com/inday/p/6288707.html HTTP is not just for serving up web pages. It’s al ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(二)-- Web Api Demo
在上一篇里,我已经建立了一个简单的Web-Demo应用程序.这一篇将记录将此Demo程序改造成一个Web Api应用程序. 一.添加ASP.NET Core MVC包 1. 在project.json ...
- ASP.NET Core 中基于工厂的中间件激活
IMiddlewareFactory/IMiddleware 是中间件激活的扩展点. UseMiddleware 扩展方法检查中间件的已注册类型是否实现 IMiddleware. 如果是,则使用在容器 ...
- 在ASP.NET Core中添加的Cookie如果含有特殊字符,会被自动转义
我们知道在Cookie中有些字符是特殊字符,这些字符是不能出现在Cookie的键值中的. 比如"="是Cookie中用来分隔键和值的特殊字符,例如:Key01=Value01,表示 ...
- ASP.NET Core中的OWASP Top 10 十大风险-跨站点脚本攻击 (XSS)
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
C# 嵌入dll 在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- 在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度
在这篇文章中,我将介绍如何使用ASP.NET Core托管服务运行Quartz.NET作业.这样的好处是我们可以在应用程序启动和停止时很方便的来控制我们的Job的运行状态.接下来我将演示如何创建一个简 ...
随机推荐
- SpringCloud之Feign:REST客户端
在Spring Cloud集群中,各个角色的通信基于REST服务,在调用服务时,需要使用REST客户端,常用,除了使用Spring自带的RestTemplate,也可使用另一个REST客户端:Feig ...
- VS2017无法打开Razor视图文件提示:引发类型"System.Exception"异常
背景介绍 由于电脑装了R#(吃内存大户),导致VS2017打开项目慢以及卡顿,因此在扩展和更新这个功能里面将没用的插件关闭了,导致.NET CORE的Razor视图文件打不开(真心是一脸懵逼,关个插件 ...
- java开发实习生面试经历
这是我第一次写博客,以前都是查看别人的博客分享学习技术,转眼间我也成为其中一员.从一位初学者到现在的开发实习生,不断前进着,跟随时代的脚步在程序的海洋里漂泊,也意识到自己的各种不足,但我还年轻,头还 ...
- C#后台架构师成长之路-基础体系篇章大纲
如下基础知识点,如果不熟透,以后容易弄笑话..... 1. 常用数据类型:整型:int .浮点型:double.布尔型:bool.... 2. 变量命名规范.赋值基础语法.数据类型的转换.运算符和选择 ...
- 在 Cocos2d-x 中添加自己的微博链接
配置:OS X 10.10 + Xcode 6.0 + Cocos2d-x-3.2 一.Android 端代码 1.在 Cocos2dxActivity.java 中添加openUrl函数并导入响应包 ...
- 检测服务器是否开启重协商功能(用于CVE-2011-1473漏洞检测)
背景 由于服务器端的重新密钥协商的开销至少是客户端的10倍,因此攻击者可利用这个过程向服务器发起拒绝服务攻击.OpenSSL 1.0.2及以前版本受影响. 方法 使用OpenSSL(linux系统基本 ...
- RTP通用头部扩展
概览 本文为阅读RFC5285时对RTP头部扩展的记录笔记,介绍了one-byte-header和two-byte-header情况下的rtp头部扩展 rtp头部扩充 在RFC3550中, 一个通用的 ...
- CF1062F Upgrading Cities
题意 由于这是个\(DAG\),我们考虑拓朴排序,求某个点能到的和能到它的点,这是两个问题,我们可以正反两边拓朴排序,这样就只用考虑它能到的点了 设\(f[x]\)表示\(x\)能到的点数\(+\)能 ...
- .NET Core 数据结构与算法 1-1
.NET Core 数据结构与算法 1-1 本节内容为顺序表 简介 线性表是简单.基本.常用的数据结构.线性表是线性结构的抽象 (Abstract),线性结构的特点是结构中的数据元素之间存在一对一的线 ...
- django中使用pandas Django-pandas
在django中使用pandas操作django的ORM查询出来的QuerySet对象,可以使用插件django-pandas. 截止教程书写时间,django-pandas已发布到0.6.1. 依赖 ...