第 8 章 认证和安全

配置数据保护

在默认的情况下,数据保护 API 有自身的默认配置,如密钥的保存位置、密钥的有效期、所使用的算法等

前面已经提到了密钥的默认有效期以及用到的算法,对于密钥的保存位置,根据应用程序运行环境的不同,密钥的保存位置也不相同

保存密钥的文件名为 kdy-{guid}.xml,其中 guid 是密钥 ID

如果要修改密钥的保存位置,可以调用 IDataProtectionBuilder 接口的 PersistKeysToFileSystem 方法

  1. services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo("data_keys"));

如果要修改密钥的有效期,可以调用 SetDefaultKeyLifetime 方法

  1. services.AddDataProtection().SetDefaultKeyLifetime(TimeSpan.FromDays(30));

如果要修改默认的加密算法与散列算法,可以调用 UseCryptographicAlgorithms 方法

  1. services.AddDataProtection()
  2. .UseCryptographicAlgorithms(
  3. new AuthenticatedEncryptorConfiguration
  4. {
  5. EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
  6. ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
  7. });

如果希望密文在多个应用程序之间共享,应该调用 SetApplicationName 方法来设置应用程序的名称,并使要共享密钥的应用程序具有同样的名称

  1. services.AddDataProtection().SetApplicationName("shared app name");

用户机密

在开发过程中,对于一些敏感信息,应该避免直接写在代码或配置文件中,可以通过环境变量与用户机密实现

在 Visual Studio 中,右击“解决方案管理器”中的“项目名称”,在快捷菜单栏中选择“管理用户机密”

此时会打开一个 secrets.json 的 JSON 文件,内容为空,同时在 .csporj 中,多出了如下节点

  1. <UserSecretsId>4d887da9-16a8-4a0c-b467-6b5e67a304ce</UserSecretsId>

secrets.json 文件主要用来存储敏感数据,即用户机密,主要针对开发环境

将用户机密配置到系统更中

  1. var builder = new ConfigurationBuilder()
  2. .SetBasePath(env.ContentRootPath)
  3. .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
  4. if (env.IsDevelopment())
  5. {
  6. builder.AddUserSecrets<Startup>();
  7. }
  8. Configuration = builder.Build();

访问的时候在需要的位置注入 IConfiguration 接口即可

通过 .NET Core CLI 工具同样也可以创建并管理用户机密,首先在 .csproj 文件中添加 UserSecretsId 节点,修改完项目后,在命令行提示符中切换到文件所在位置,使用命令添加、删除、查看配置项

  1. dotnet user-secrets set "Library:ServiceApiKey" "12345"
  2. dotnet user-secrets list
  3. dotnet user-secrets remove
  4. 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

添加服务到容器中

  1. services.AddCors();

使用 UseCors 方法为整个应用程序提供 CORS 功能,需要注意,CORS 中间件应添加在任何可能会用到 CORS 功能的中间件之前

  1. app.UseCors(builder => builder.WithOrigins("https://localhost:6001"));

如果要允许任何源访问,则可以使用 AllowAnyOrigin 方法

  1. app.UseCors(builder => builder.AllowAnyOrigin());

类似的方法还有 AllowAnyMethod 和 AllowAnyHeader

除了在 UseCors 方法中创建 CORS 策略外,还可以在添加 CORS 服务时通过 CorsOptions 对象创建一个或多个策略

  1. services.AddCors(options =>
  2. {
  3. options.AddPolicy("AllowAllMethodsPolicy",
  4. builder => builder.WithOrigins("https://localhost:6001").AllowAnyMethod());
  5. options.AddPolicy("AllowAnyOriginPolicy", builder => builder.AllowAnyOrigin());
  6. options.AddDefaultPolicy(builder => builder.WithOrigins("https://localhost:6001"));
  7. });

当创建多个策略后,使用 UseCors 方法就可以指定要使用的策略名称

  1. app.UseCors("AllowAllMethodsPolicy");

使用 CORS 中间件能够为整个应用程序添加 CORS 功能,如果仅希望为 MVC 应用程序中的某个 Controller 或某个 Action 添加 CORS,那么就需要 [EnableCors] 特性,此时应将 CORS 中间件从请求管道中移除

  1. [EnableCors]
  2. [Route("api/[controller]")]
  3. [ApiController]
  4. public class ValueController : Controller
  5. {
  6. 。。。
  7. [EnableCors("AllowAllMethodsPolicy")]
  8. [HttpGet]
  9. public ActionResult<IEnumerable<Student>> Get()
  10. {
  11. 。。。
  12. }
  13. }

与 [EnableCors] 特性相反,[DisableCors] 特性能够使 Controller 或 Action 禁用 CORS 支持

8.6 限流

为防止 API 被恶意滥用,应考虑对 API 的请求进行限流

下例中的自定义中间件实现了限流功能,它限制每分钟内使用同一方法对同一资源仅能发起10次请求

  1. namespace WebApplication1.Middlewares
  2. {
  3. public class RequestRateLimitingMiddleware
  4. {
  5. private const int Limit = 10;
  6. private readonly RequestDelegate next;
  7. private readonly IMemoryCache requestStore;
  8. public RequestRateLimitingMiddleware(RequestDelegate next, IMemoryCache requestStore)
  9. {
  10. this.next = next;
  11. this.requestStore = requestStore;
  12. }
  13. public async Task Invoke(HttpContext context)
  14. {
  15. var requestKey = $"{context.Request.Method}-{context.Request.Path}";
  16. int hitCount = 0;
  17. var cacheOptions = new MemoryCacheEntryOptions
  18. {
  19. AbsoluteExpiration = DateTime.Now.AddMinutes(1)
  20. };
  21. if (requestStore.TryGetValue(requestKey, out hitCount))
  22. {
  23. if (hitCount < Limit)
  24. {
  25. await ProcessRequest(context, requestKey, hitCount, cacheOptions);
  26. }
  27. else
  28. {
  29. context.Response.Headers["X-RateLimit-RetryAfter"] = cacheOptions.AbsoluteExpiration?.ToString();
  30. context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
  31. }
  32. }
  33. else
  34. {
  35. await ProcessRequest(context, requestKey, hitCount, cacheOptions);
  36. }
  37. }
  38. private async Task ProcessRequest(HttpContext context, string requestKey, int hitCount,
  39. MemoryCacheEntryOptions cacheOptions)
  40. {
  41. hitCount++;
  42. requestStore.Set(requestKey, hitCount, cacheOptions);
  43. context.Response.Headers["X-RateLimit-Limit"] = Limit.ToString();
  44. context.Response.Headers["X-RateLimit-Remaining"] = (Limit - hitCount).ToString();
  45. await next(context);
  46. }
  47. }
  48. }

上述的中间件的实现借用了内存缓存来记录以某一方法对某一资源访问的次数

由于中间件使用了内存缓存,因此确保将其服务添加进来

  1. services.AddMemoryCache();

并将中间件添加到请求管道中,注意,需要将他放在处理 API 请求之前

  1. app.UseMiddleware<RequestRateLimitingMiddleware>();
  2. app.UseMvc();

RequestRateLimitingMiddleware 中间件仅是简单地实现了限流功能,如果要为应用程序添加更复杂、更高级的限流功能,可借助第三方库,如 AspNetCoreRateLimit,能够根据 IP 地址或客户端 ID 对请求进行限流,同时它也支持对不同的接口设置不同的访问限制

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(尾)的更多相关文章

  1. 使用ASP.NET Core构建RESTful API的技术指南

    译者荐语:利用周末的时间,本人拜读了长沙.NET技术社区翻译的技术标准<微软RESTFul API指南>,打算按照步骤写一个完整的教程,后来无意中看到了这篇文章,与我要写的主题有不少相似之 ...

  2. 4类Storage方案(AS开发实战第四章学习笔记)

    4.1 共享参数SharedPreferences SharedPreferences按照key-value对的方式把数据保存在配置文件中,该配置文件符合XML规范,文件路径是/data/data/应 ...

  3. 菜单Menu(AS开发实战第四章学习笔记)

    4.5 菜单Menu Android的菜单主要分两种,一种是选项菜单OptionMenu,通过按菜单键或点击事件触发,另一种是上下文菜单ContextMenu,通过长按事件触发.页面的布局文件放在re ...

  4. [Android]《Android艺术开发探索》第一章读书笔记

    1. 典型情况下生命周期分析 (1)一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart方法就会被调用. (2)当用户打开新的Activity或者切换到桌面的时候,回调如下 ...

  5. 温故知新,使用ASP.NET Core创建Web API,永远第一次

    ASP.NET Core简介 ASP.NET Core是一个跨平台的高性能开源框架,用于生成启用云且连接Internet的新式应用. 使用ASP.NET Core,您可以: 生成Web应用和服务.物联 ...

  6. 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践

    本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...

  7. 零基础ASP.NET Core WebAPI团队协作开发

    零基础ASP.NET Core WebAPI团队协作开发 相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了.网上也有很多介绍这方面的文章,写的都很好.我这里提这个是因为接下来我要分享的内容 ...

  8. ASP.NET Core WebApi构建API接口服务实战演练

    一.ASP.NET Core WebApi课程介绍 人生苦短,我用.NET Core!提到Api接口,一般会想到以前用到的WebService和WCF服务,这三个技术都是用来创建服务接口,只不过Web ...

  9. 从 0 使用 SpringBoot MyBatis MySQL Redis Elasticsearch打造企业级 RESTful API 项目实战

    大家好!这是一门付费视频课程.新课优惠价 699 元,折合每小时 9 元左右,需要朋友的联系爱学啊客服 QQ:3469271680:我们每课程是明码标价的,因为如果售价为现在的 2 倍,然后打 5 折 ...

  10. Asp.Net Core 5 REST API - Step by Step

    翻译自 Mohamad Lawand 2021年1月19日的文章 <Asp.Net Core 5 Rest API Step by Step> [1] 在本文中,我们将创建一个简单的 As ...

随机推荐

  1. zzuli 1908

    ***做的时候判断当前位置为.的上下左右是否为*,如果全是改位置就改为*,如果四周中有为.,再DFS一下,其实就相当于把判断化为更小的子问题*** #include<iostream> # ...

  2. 大数相加 a+b

    #include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #i ...

  3. Liunx快捷命令(别名)与快捷方式(软/硬链接)

    一.快捷命令(别名)-临时生效1.命令:alias 别名='原命令' 2.举例:给检查防火墙的命令设置别名 [root@localhost ~]# alias fhq='firewall-cmd -- ...

  4. 机器学习-无监督机器学习-kmeans-17

    目录 1. 什么是聚类 2. 代码实现 1. 什么是聚类 无监督机器学习的一种 输入数据只有X 没有y 将已有的数据 根据相似度 将划分到不同的簇 (花团锦簇) 步骤: 随机选择k个簇的中心点 样本根 ...

  5. [转帖]mysql 里 CST 时区的坑

    mysql 里 CST 时区的坑 一.问题简述 mysql 里 CST 时区是个非常坑的概念,因为在 mysql 里CST既表示中国也表示美国的时区.但是在Jdk代码里,CST 这个字符串被理解为Ce ...

  6. [转帖]018、数据库管理之TiDB升级

    升级 使用TiUP进行补丁升级(HotFix) 版本升级流程 升级准备-更新TiUP 升级准备- 编辑TiUP Cluster 升级准备- 集群监控状态检查 升级TiDB 集群 验证TiDB集群升级结 ...

  7. [转帖]CentOS7上systemctl的使用

    https://www.cnblogs.com/yeyuzhuanjia/p/14676182.html CentOS 7.x开始,CentOS开始使用systemd服务来代替daemon,原来管理系 ...

  8. [转帖]ioping测试

    https://www.cnblogs.com/ishmaelwanglin/p/10839702.html 一个实时显示磁盘io延时的工具,以类似ping 的输出一样展示输出结果 常用参数: -c ...

  9. 【转帖】《MySQL高级篇》四、索引的存储结构

    1. 为什么使用索引 假如给数据使用 二叉树 这样的数据结构进行存储,如下图所示 2.索引及其优缺点 2.1 索引概述 2.2 优点 类似大学图书馆建书目索引,提高数据检索的效率,降低 数据库的 IO ...

  10. Nginx 系列 | (转)Nginx 上传文件:client_max_body_size 、client_body_buffer_size

    原文:http://php-note.com/article/detail/488 client_max_body_size client_max_body_size 默认 1M,表示 客户端请求服务 ...