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的运行状态.接下来我将演示如何创建一个简 ...
随机推荐
- 通过U盘在物理机安装CentOS出现Timeout的问题
错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.
- pycharm中将文件目录标记为sources root和sys.path.append()效果一样
之前遇到一个问题,先放上项目目录图 右边是main.py,它要引用的一个模块是在LPRNET目录下的一个文件,但是从右边可以看到pycharm有红色的线提示有错误.但是由于我们append函数将该目录 ...
- python-将一个列表切分成多个小列表
list是python中较为常见的数据类型,它是一个可迭代对象,迭代是什么?简单的可以理解成:一个可以被for循环遍历的对象 今天拿到一个类似这样的list list_info = ['name zh ...
- 【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案
引子 现如今手游开发中网络编程是必不可少的重要一环,如果使用的是TCP协议的话,那么不可避免的就会遇见TCP粘包和拆包的问题,马三觉得haifeiWu博主的 TCP 粘包问题浅析及其解决方案 这篇博客 ...
- Elasticsearch从入门到放弃:索引基本使用方法
前文我们提到,Elasticsearch的数据都存储在索引中,也就是说,索引相当于是MySQL中的数据库.是最基础的概念.今天分享的也是关于索引的一些常用的操作. 创建索引 curl -X PUT & ...
- python进程基础点整理
操作系统 串行: 一个程序完完整整的执行完再执行下一个 并发: 看起来像是同时运行,其实就是程序间的切换频率比较快,看不出来 并行:真正的同时运行 多道技术 空间复用:共用一个内存条,多个进程相互隔离 ...
- Selenium模块的安装
Selenium模块 1.安装selenium python2:pip install selenium python3:pip install selenium 2.设置浏览器驱动 解压后必须与浏览 ...
- Python Web(三)
Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.Django母版渲染 1.创建母版文件 base.html <!DOCTYPE html> < ...
- 记录:c#实现微信,支付宝扫码支付(一)
因为公司系统业务需要,这几天了解了一下微信和支付宝扫码支付的接口,并用c#实现了微信和支付宝扫码支付的功能. 微信支付分为6种支付模式:1.付款码支付,2.native支付,3.jsapi支付,4.a ...
- viewPager作为RecyclerView的itemView出现的显示问题
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/174 ViewPager作为RecyclerView的it ...