《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(尾)
第 8 章 认证和安全
配置数据保护
在默认的情况下,数据保护 API 有自身的默认配置,如密钥的保存位置、密钥的有效期、所使用的算法等
前面已经提到了密钥的默认有效期以及用到的算法,对于密钥的保存位置,根据应用程序运行环境的不同,密钥的保存位置也不相同
保存密钥的文件名为 kdy-{guid}.xml,其中 guid 是密钥 ID
如果要修改密钥的保存位置,可以调用 IDataProtectionBuilder 接口的 PersistKeysToFileSystem 方法
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo("data_keys"));
如果要修改密钥的有效期,可以调用 SetDefaultKeyLifetime 方法
services.AddDataProtection().SetDefaultKeyLifetime(TimeSpan.FromDays(30));
如果要修改默认的加密算法与散列算法,可以调用 UseCryptographicAlgorithms 方法
services.AddDataProtection() .UseCryptographicAlgorithms( new AuthenticatedEncryptorConfiguration { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 });
如果希望密文在多个应用程序之间共享,应该调用 SetApplicationName 方法来设置应用程序的名称,并使要共享密钥的应用程序具有同样的名称
services.AddDataProtection().SetApplicationName("shared app name");
用户机密
在开发过程中,对于一些敏感信息,应该避免直接写在代码或配置文件中,可以通过环境变量与用户机密实现
在 Visual Studio 中,右击“解决方案管理器”中的“项目名称”,在快捷菜单栏中选择“管理用户机密”
此时会打开一个 secrets.json 的 JSON 文件,内容为空,同时在 .csporj 中,多出了如下节点
<UserSecretsId>4d887da9-16a8-4a0c-b467-6b5e67a304ce</UserSecretsId>
secrets.json 文件主要用来存储敏感数据,即用户机密,主要针对开发环境
将用户机密配置到系统更中
var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); if (env.IsDevelopment()) { builder.AddUserSecrets<Startup>(); } Configuration = builder.Build();
访问的时候在需要的位置注入 IConfiguration 接口即可
通过 .NET Core CLI 工具同样也可以创建并管理用户机密,首先在 .csproj 文件中添加 UserSecretsId 节点,修改完项目后,在命令行提示符中切换到文件所在位置,使用命令添加、删除、查看配置项
dotnet user-secrets set "Library:ServiceApiKey" "12345" dotnet user-secrets list dotnet user-secrets remove dotnet user-secrets clear
8.5 CORS
CORS,全称 Cross-Origin Resource Sharing (跨域资源共享),是一种允许当前域的资源能被其他域访问的机制
所谓同域,是指两个 URL 有相同的协议、主机和端口,如果三项中有一项不同,那么资源就会认为来自不同的域
对于跨域资源访问,CORS 会将它们分为两种类型:简单请求和非简单请求
一个请求如果满足以下所有条件,就是简单请求:
- 请求方法为 GET、HEAD、POST 三者之一
- 如果请求方法为 POST,则 Content-Type 消息头只允许为这3项:application/x-www-form-urlencoded、multipart/form-data、text/plain
- 不包含自定义消息头
如果不满足其中任何一个条件,则为非简单请求
如果是简单请求,被请求的服务器会判断这个源是否包含在允许跨源访问的列表中,包含则允许访问
如果是非简单请求,则在向服务器发送实际请求之前,先发送一个 OPTIONS 方法的请求,以确认发送正式的请求是否安全
实现 CORS
添加服务到容器中
services.AddCors();
使用 UseCors 方法为整个应用程序提供 CORS 功能,需要注意,CORS 中间件应添加在任何可能会用到 CORS 功能的中间件之前
app.UseCors(builder => builder.WithOrigins("https://localhost:6001"));
如果要允许任何源访问,则可以使用 AllowAnyOrigin 方法
app.UseCors(builder => builder.AllowAnyOrigin());
类似的方法还有 AllowAnyMethod 和 AllowAnyHeader
除了在 UseCors 方法中创建 CORS 策略外,还可以在添加 CORS 服务时通过 CorsOptions 对象创建一个或多个策略
services.AddCors(options => { options.AddPolicy("AllowAllMethodsPolicy", builder => builder.WithOrigins("https://localhost:6001").AllowAnyMethod()); options.AddPolicy("AllowAnyOriginPolicy", builder => builder.AllowAnyOrigin()); options.AddDefaultPolicy(builder => builder.WithOrigins("https://localhost:6001")); });
当创建多个策略后,使用 UseCors 方法就可以指定要使用的策略名称
app.UseCors("AllowAllMethodsPolicy");
使用 CORS 中间件能够为整个应用程序添加 CORS 功能,如果仅希望为 MVC 应用程序中的某个 Controller 或某个 Action 添加 CORS,那么就需要 [EnableCors] 特性,此时应将 CORS 中间件从请求管道中移除
[EnableCors] [Route("api/[controller]")] [ApiController] public class ValueController : Controller { 。。。 [EnableCors("AllowAllMethodsPolicy")] [HttpGet] public ActionResult<IEnumerable<Student>> Get() { 。。。 } }
与 [EnableCors] 特性相反,[DisableCors] 特性能够使 Controller 或 Action 禁用 CORS 支持
8.6 限流
为防止 API 被恶意滥用,应考虑对 API 的请求进行限流
下例中的自定义中间件实现了限流功能,它限制每分钟内使用同一方法对同一资源仅能发起10次请求
namespace WebApplication1.Middlewares { public class RequestRateLimitingMiddleware { private const int Limit = 10; private readonly RequestDelegate next; private readonly IMemoryCache requestStore; public RequestRateLimitingMiddleware(RequestDelegate next, IMemoryCache requestStore) { this.next = next; this.requestStore = requestStore; } public async Task Invoke(HttpContext context) { var requestKey = $"{context.Request.Method}-{context.Request.Path}"; int hitCount = 0; var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpiration = DateTime.Now.AddMinutes(1) }; if (requestStore.TryGetVa 1a49 lue(requestKey, out hitCount)) { if (hitCount < Limit) { await ProcessRequest(context, requestKey, hitCount, cacheOptions); } else { context.Response.Headers["X-RateLimit-RetryAfter"] = cacheOptions.AbsoluteExpiration?.ToString(); context.Response.StatusCode = StatusCodes.Status429TooManyRequests; } } else { await ProcessRequest(context, requestKey, hitCount, cacheOptions); } } private async Task ProcessRequest(HttpContext context, string requestKey, int hitCount, MemoryCacheEntryOptions cacheOptions) { hitCount++; requestStore.Set(requestKey, hitCount, cacheOptions); context.Response.Headers["X-RateLimit-Limit"] = Limit.ToString(); context.Response.Headers["X-RateLimit-Remaining"] = (Limit - hitCount).ToString(); await next(context); } } }
上述的中间件的实现借用了内存缓存来记录以某一方法对某一资源访问的次数
由于中间件使用了内存缓存,因此确保将其服务添加进来
services.AddMemoryCache();
并将中间件添加到请求管道中,注意,需要将他放在处理 API 请求之前
app.UseMiddleware<RequestRateLimitingMiddleware>(); app.UseMvc();
RequestRateLimitingMiddleware 中间件仅是简单地实现了限流功能,如果要为应用程序添加更复杂、更高级的限流功能,可借助第三方库,如 AspNetCoreRateLimit,能够根据 IP 地址或客户端 ID 对请求进行限流,同时它也支持对不同的接口设置不同的访问限制
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
- 微软ASP.NET 电商网站开发实战 MVC6 +HTML5 +WCF+WebAPI+NoSQL+mongoDB+Redis+Core视频 代码 面试题
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- AspNet Core Api Restful +Swagger 实现微服务之旅(四)
- ASP.NET Core 实战:构建带有版本控制的 API 接口
- Asp.Net Core WebAPI实战9
- asp.net core跨平台开发从入门到实战文摘
- AspNet Core Api Restful 实现微服务之旅 (一)
- Asp.Net Core WebAPI实战6
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(二)-- Web Api Demo
- ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目
- 视频教程-ASP.NET Core跨平台开发实战-.NET
- Asp.Net Core WebAPI实战7
- Asp.Net Core WebAPI实战8
- Asp.Net Core WebAPI实战3
- 在docker中运行ASP.NET Core Web API应用程序(附AWS Windows Server 2016 widt Container实战案例)
- ASP.NET Core 实战:使用ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目
- 零基础ASP.NET Core WebAPI团队协作开发
- 《ASP.NET Core跨平台开发从入门到实战》Web API自定义格式化protobuf
- ASP.NET Core WebAPI 开发-新建WebAPI项目 转
- 零基础ASP.NET Core WebAPI团队协作开发