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的运行状态.接下来我将演示如何创建一个简 ...
随机推荐
- Android8.1 SystemUI源码分析之 Notification流程
代码流程 1.先看UI显示,StatuBar加载 CollapsedStatusBarFragment 替换 status_bar_container(状态栏通知显示区域) SystemUI\src\ ...
- Scrum Framework, Process and Story Point
Scrum Framework Roles Ceremonies Artifacts Scrum Master Sprint Planning Product Backlog Product Owne ...
- 快速搭建用于测试的rtsp协议网络流媒体数据服务
背景: 最近根据项目需求,在平台系统中加入了视频监控显示功能,但是限于没有提供真实可用的监控摄像头数据,通过EasyScreenLive快速搭建了一个rtsp的流媒体服务,下面将实现步骤分享给大家,为 ...
- 深入浅出xpath轴定位
在web自动化里面经常要用到定位,常用的八种定位方式中我最喜欢xpath定位,功能很强大.结合它里面的文本定位.模糊定位.逻辑定位等,基本能搞定所有的元素定位问题. 今天要讨论的是xpath的另一种比 ...
- 安装swoole出现make报错的原因与解决方法
安装swoole报错,错误信息如下: 报错原因 报错很明显,找不到 openssl/ssl.h ,首先要确认电脑上有没有安装 openssl Mac安装openssl 既然它找不到,那么就需要手动的指 ...
- Ant Design Pro 改变默认启动端口号
找到package.json文件,找到图位置加--port即可.
- C# winfrom调用摄像头扫描二维码(完整版)
前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途.发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下. 参考博客链接:https://www.cnbl ...
- 根据excle说明文档建表
在Excel里整理好的表模型数据,可直接导入PowerDesigner.此功能通过PowerDesigner的脚本功能来实现,使用起来也简单.具体操作方法: 打开PowerDesigner,新 ...
- Scss换肤
项目中虽然没有一键换肤的要求,但是产品要求后期能换主题.在开发组件中涉及到主题的地方,要提取一些公用的变量,不要直接写死样式值.但是如果只是定义一些变量的话,只是完成控制颜色等值的提取.后期切换的话需 ...
- JavaScript基础6
计时器 setInterval() 按照指定周期来调用函数或计算表达式 以毫秒计算 语法 setInterval(code,millisec[,“lang”]) code 要调用的函 ...