用ASP.NET Core 2.1 建立规范的 REST API -- 保护API和其它

预备知识: 

 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 

 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) + 准备项目

建立成熟度2级的 API请看这里:

用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST用ASP.NET Core 2.0 建立规范的 REST API -- DELETE, UPDATE, PATCH 和 Log用ASP.NET Core 2.1 建立规范的 REST API -- 翻页/排序/过滤等

HATEOAS:用ASP.NET Core 2.1 建立规范的 REST API -- HATEOAS

缓存和并发:用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发

本文所需项目代码(右键另存, 后缀改为zip): https://images2018.cnblogs.com/blog/986268/201806/986268-20180612151833673-1851218969.jpg

认证和授权

认证/身份验证 Authentication, 是验证想要访问特定资源的人/系统的身份的过程.

授权 Authorization, 是确认已认证的用户拥有足够的权限去做某些事的过程.

打个比喻: 认证是一个人可以进入到房间的权限, 而授权则表明这个人可以在房间内做哪些事.

 

认证的过程可以和应用程序分开并且还可以被其它的服务使用, 但是授权的过程通常是针对某个应用程序, 不同的角色会拥有不同的权限.

 

HTTP协议提供了一个协商访问被保护资源的机制, 下图就是HTTP认证:

640?wx_fmt=jpeg

标准的认证流程开始于一个访问服务器被保护资源的匿名请求, HTTP服务器随后处理了该请求并决定拒绝让它访问被保护的资源, 因为该请求没有凭据; 随后HTTP Server发送了一个WWW-Authenticate Header回去, 这表示它需要这套认证方案. 然后客户端再次发送请求的时候包含了一个Authorization Header, 它的值符合HTTP Server的认证方案. 当服务器收到这次请求时, 它验证了Authorization Header里的凭据, 并让请求通过了管道.

服务器可以提供多种认证方案, 客户端只需选择其中一种即可, 上图中使用的是Basic 认证方案. 还有其它的认证方案:

  • 匿名 Anonymous 也可以当作是一种方案吧, 就当作是授权给所有人好了

  • Basic 认证方案, 它是一种比较老的方案, n年前经常被使用. 它太简单了, 它的值是含有用户名和密码组成的字符串, 并用冒号(:)连接, 并且编码为Base64字符串. 例如username为dave, 密码为1234, 那么Authorization Header的值就是: Authorization: Basic ZGF2ZToxMjM0.

  • Digest 认证方案, 它作为Basic的代替者出现的. 服务器会给客户端发送一个随机字符串作为一个challenge(盘问, 质疑, 挑战), 这个随机字符串叫做nonce(可以理解为临时生成的字符串). 而客户端通过发送一个带有用户名, 密码, nonce和其它信息的hash来进行认证.

  • Bear 认证方案, 它是最流行也是更安全的认证方案. 它使用Bearer Tokens (承载令牌) 来访问由OAuth 2.0协议保护的资源. 任何拥有bearer token的人都可以访问相关的资源. bearer token的生命周期通常很短, 会过期. 例子: Authorization: Bearer: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c.

  • NTLM认证方案, 它是NTLAN Manager的缩写, 它是一种挑战--响应的方案, 要比Digest更安全. 这种方案使用Windows凭据来转化盘问的数据, 而不是使用编码的凭据.

  • Negotiate 认证方案, 它会自动选择NTLM方案和Kerberos协议中的一个, Kerboros协议比NTLM快.

后两种方案都仅限于Windows系统.

这几种方案里Basic提供的保护程度/级别最低, 而Negotiate最高/强.

ASP.NET Core可选择的认证提供商就很多了, 例如ASP.NET Core Identity. 但是它主要用于包含页面的web应用, 例如MVC或Razor Page, 并不适用于REST/Web API, 所以不介绍它了.

如果应用部署在云上, 可以使用Azure Active Directory(AAD) 和 Azure Active Directory B2C (Azure AD B2C). 我没用过, 就不介绍了.

第三方的认证提供商有很多: AspNet.Security.OpenIdConnect.Server(ASOS), IdentityServer4, OpenIddict, Pwdless.....

我一直在用Identity Server 4, 但是这里不会深入介绍, 这里主要介绍如何实现REST API, 如果有需要的话, 可以写一系列关于Identity Server 4的文章.

 

选项很多, 但是要实现的话还需要了解JSON Web Tokens (JWT), 它是一个基于JSON的开放工业标准, 它用于为双方表示一些声明. 它提供了一种紧凑的, 自包含的方式在双方之间用JSON对象来传输信息.

JWT使用 HMAC secret 或 RAS公有和私有键对(key pair) 这两种方式来进行签名.

JWT由三部分组成: headerpayloadsignature. 形式如下面的伪代码: [X=base64(header)].[Y=base64(payload)].[signature([X].[Y])] .

去这个网址可以更直观的理解这三部分: jwt.io

JWT token最终是一个字符串, 它的三个部分用点(.)分开, 前两部分(header payload)是Base64编码的字符串; 最后一部分是前两个Base64字符串的组合, 也是用点(.)分开并进行了签名, 如下图:

640?wx_fmt=png

 

 使用Bearer方案和JWT的流程如下:

640?wx_fmt=png

 

配置项目, 在Startup的ConfigureServices里:

640?wx_fmt=png

如果使用Identity Server 4的话, 这里就可以不这样写了.

首先我们配置使用Bearer认证方案, 然后通过AddJwtBearer设定一些参数. Configuration里面的值可以放在appSettings.json里面或者其它地方:

640?wx_fmt=png

然后在Configure方法里调用app.UseAuthentication()方法, 要在app.UseMvc()之前调用:

640?wx_fmt=png

最后使用[Authorize]属性标签把CountryController保护起来, 也可以应用于Action级:

640?wx_fmt=png

发送不带Authorization Header的请求来测试:

640?wx_fmt=png

返回 401 Unauthorized 未授权.

640?wx_fmt=jpeg

返回的Header里面告诉我们应该使用Bearer认证方案.

 

下面我们需要一个可以生成JWT token的节点, 针对本文我就在本项目里建立这个节点吧:

640?wx_fmt=png

请求token的地址是 /api/authentication, 请求token用的是Basic方案, Post方法里就是先解码, 验证用户名和密码, 成功后调用GenerateToken生成token.

那就按要求再次发送请求:

640?wx_fmt=png

注意这里usename:password的base64编码是: dXNlcm5hbWU6cGFzc3dvcmQ=

现在我获得了token, 然后我用token再次请求Country资源:

640?wx_fmt=png

资源就可以正常的访问了.

 

想要解析这个token, 需要到jwt.io:

640?wx_fmt=png

箭头处需要填上secret.

 

这个例子比较简单, 实际应用中还是使用Identity Server 4之类的东西吧.

 

使用HTTPS

根据官方文档(https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&tabs=visual-studio#require-https), 它建议ASP.NET Core web应用都应该调用HTTPS重定向中间件, 这样就可以把所有的HTTP请求转换为HTTPS.

只需要在Startup的Configure方法里调用UseHttpsRedirection()方法即可:

640?wx_fmt=png

而在ConfigureServices方法里可以配置这个中间件:

640?wx_fmt=png

 

HSTS (HTTP 严格的传输安全协议)

web应用通过使用特殊的响应header可以选择使用加强的安全协议OWASP(Open Web Application Security Project), HSTS(HTTP Strict Transport Security). 当所支持的浏览器接收到这个header的时候, 浏览器就会阻止任何通过HTTP到指定域名的通信, 会使用HTTPS代替. 同时它也会阻止从浏览提的提示框点击的HTTPS.

为实现这个只需要在Startup的Configure里使用:

640?wx_fmt=png

 

 一般不建议在开发环境使用Hsts, 因为浏览器极有可能会缓存HSTS 的header. 默认情况下, UseHsts会排除本地回路的地址.

UseHsts会排除下列回路宿主:

  • localhost : IPv4 回路地址.

  • 127.0.0.1 : IPv4 回路地址.

  • [::1] : IPv6 回路地址.

可以在ConfigureServices方法里对它进行配置:

640?wx_fmt=png

这部分具体请查看文档: https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&tabs=visual-studio#http-strict-transport-security-protocol-hsts

 

CORS 跨域请求

配置注册CORS需要在Startup的ConfigureServices方法完成:

640?wx_fmt=png

针对整个应用启用CORS需要在Configure方法里调用下面的方法:

640?wx_fmt=png

应该尽早的调用该方法, 以便在它后边注册的节点都可以被跨域访问.

这是第一种方法, 使用的是lambda表达式.

注意URL地址结尾不要有/, 它会引起错误.

这种方法使用的是CorsPolicyBuilder 类, 它拥有Fluent API, 可以串接方法调用:

640?wx_fmt=png

 

第二种方法是使用策略.

在ConfigureServices里配置好命名的策略:

640?wx_fmt=png

在Configure方法里使用该策略:

640?wx_fmt=png

另外也可以不适用UseCors(), 而是在下面这几种级别指定使用该策略:

Action级别:

640?wx_fmt=png

Controller级别:

640?wx_fmt=png

全局Controller级别:

640?wx_fmt=png

这么用的话, 需要禁用CORS策略就:

640?wx_fmt=png

 

关于CORS的具体配置, 还是请参考官方文档: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1

 

Rate Limiting 速率限制

速率限制是指限制被允许的请求到API(或某个特定的资源)。这样就可以保护API,避免一些非正常使用的场景,例如网络爬虫或请求太多而导致API的性能严重下降,Dos和DDos。针对这点我们采取的节流策略是控制允许访问API的请求的频率/速率,它可以决定特定的请求是否被允许。

例如客户端只允许每小时有100个请求到达API,也可以按天计算,还可以带着IP地址一起限制。

响应的Header可以用来表示速率限制,但是这些Header并不是HTTP标准。这些header都以X-Rate-Limit开头。

  • X-Rate-Limit-Limit, 这个表示添加了限制并包含了限制的有效期。

  • X-Rate-Limit-Remaining,表示该客户还剩下多少个被允许的请求。

  • X-Rate-Limit-Reset,提供关于何时限制会被重置的时间信息。

如果达到限制了,这些响应会返回429 Too many requests 状态码。有可能会包含一个Retry-After 响应Header,而响应的body应该包含解释当前状态的细节信息。当然这都是理论上要求的。

 

下面去实现,首先安装这个库 AspNetCoreRateLimit (https://github.com/stefanprodan/AspNetCoreRateLimit):

640?wx_fmt=png

首先在Startup的ConfigureServices里面注册,用到了MemoryCache:

640?wx_fmt=png

这里配置的是IP限制,它允许有很多规则,这里我只用了一个:针对所有的资源,每5分钟最多3次请求。

现在,我需要注册一个策略存储和速率限制计数器的存储,这两个是被中间件使用。所以还需要注册这两个服务:

640?wx_fmt=png

这里都使用的是Singleton单例,因为我们需要的是针对全局的请求来做操作。

接下来要在管道里添加中间件,它应该放在靠前的位置,在日志和异常之后:

640?wx_fmt=png

 

测试,发送一个请求看结果:

640?wx_fmt=png

可以看到5分钟内还剩下两次请求的配额。限制重置的时间大约在5分钟之后。

发送请求超限之后,就会返回429:

640?wx_fmt=png

Retry-After提示了再过294秒后可以再试试。。。

而响应的body是这样提示的:

640?wx_fmt=png

 

我们再组合几个其它的规则:

640?wx_fmt=png

现在允许5分钟10次请求,但是每10秒钟最多只能有两次请求。

第一次请求后:

640?wx_fmt=png

5分钟内还剩9次,然后我10秒内连续发送两次请求,然后再发送一次请求:

640?wx_fmt=png

这时超出了限制,Header里:

640?wx_fmt=png

提示6秒后可以重试, 6秒后再次发送请求:

640?wx_fmt=png

 

这个库还是挺灵活强大的,更多功能还需要看官方文档。

 

API 文档

业界通常会使用Swagger OpenAPI来对RESTful API进行格式化描述,而Swagger OpenAPI的当前版本是v3.

ASP.NET Core有一个第三方库Swashbuckle,它支持Swagger,但是只支持版本2,版本2有个重要的缺陷就是不支持Action重载,之前HATEOAS的文章里提到过我们需要使用这种重载。所以Swashbuckle暂时并不是完全合适,所以我就不装它了。

就暂时不弄自动文档了。。。

 

单元测试

需要使用到xUnit和Moq,这里不介绍了。

关于xUnit,我写过几篇文章,有兴趣可以参考下:

http://www.cnblogs.com/cgzl/p/8283610.html

http://www.cnblogs.com/cgzl/p/8287588.html

http://www.cnblogs.com/cgzl/p/8438019.html

http://www.cnblogs.com/cgzl/p/8444423.html 

Moq的文章博客园应该有,如果需要的话,我可以写一下。

 

其它

其它可能需要了解的包括:POSTMAN/Newman自动化测试,CI,CD,GraphQL等等。我就不介绍了 

这个系列文章就到这了。

源码(我还需要整理一下源码,现在有点乱):https://github.com/solenovex/ASP.NET-Core-2.0-RESTful-API-Tutorial

相关文章:

原文地址: https://www.cnblogs.com/cgzl/p/9165388.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CERC2017 Gambling Guide,最短路变形,期望dp

题目链接 题面链接 题意 给定一个无向图,你需要从11点出发到达n" role="presentation" style="position: relative;">nn点,你在每一点的时候,使用11个单位的代价,随机得到相邻点的票,但是你可以选择留在原地…

P4045-[JSOI2009]密码【AC自动机,状压dp】

正题 题目链接:https://www.luogu.com.cn/problem/P4045 题目大意 给nnn个字符串,求有多少个长度为lll的字符串包含所有给出的字符串 解题思路 因为nnn很小,考虑状压dpdpdp,因为是包含所有字符串,考虑在ACACAC自动机上dpdpdp。…

华为资深工程师:码农很多,但程序员并不多......

“春节假期,与几位友人小聚,大家互道工作顺利、平安健康云云......期间一位驰骋商界多年的老友问:“你现在在华为做什么工作呀?”我很骄傲地说:”系统架构师“,可是他却愣了很久。但当我老婆在旁边补上一句“码农“时…

【DP】【递归】分离与合体

分离与合体 题目大意: 有n个区域,可以把它们分为两个区间,结果加上左边区间的最左区域的数和最右区域的数还有右边区间的最右区域的数,就这样不停分,使结果最大,并输出各分界线的位置(按1/2,2…

NEERC2017 Laminar Family 树链剖分+LCA

题目链接 http://codeforces.com/gym/101630/attachments/download/6401/20172018-acmicpc-northeastern-european-regional-contest-neerc-17-en.pdf 题意 给出一棵树和一组操作,操作的格式是给出u、vu、v两个节点,并将该节点所确定的路径上的节点全…

CF1009F-Dominant Indices【长链剖分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1009F 题目大意 以1为根的一棵树,对于每个节点xxx求一个最小的kkk使得以xxx为根的子树中第kkk层的结点最多。 解题思路 我们先进行一次长链剖分,对于一个长链我们可以发现如果每次往下做的话&#…

VS2017 15.8第二个预览版本提升了对CPU Profiling和F#的支持

VS2017 15.8第一个预览版本的特性包括对ARM64构建的支持、ASP.NET Core对Docker的支持以及重新引入LibMan。在15.8的第二个预览版本中,微软发布了一个新Google Android模拟器的预览功能,它能够与Hyper-V兼容。这样的话,最新的Android模拟器就…

【SPFA】腾讯大战360

腾讯大战360 题目大意: 有n个点,还有m条线连接着这些点,有两个人在其中两个点上,让这两个人相遇最快要多久 原题: 题目描述 2010年11月3日,是一个难忘的日子。 腾讯发布消息:存360则&#…

一道有趣的最短路 NEERC2017 Journey from Petersburg to Moscow

题目链接 http://codeforces.com/gym/101630/attachments/download/6401/20172018-acmicpc-northeastern-european-regional-contest-neerc-17-en.pdf 题意 求11到n" role="presentation" style="position: relative;">nn的最短路,最…

P5904-[POI2014]HOT-Hotels加强版【长链剖分,dp】

正题 题目链接:https://www.luogu.com.cn/problem/P5904 题目大意 nnn个点的一棵树,求有多少个点对(i,j,k)(i,j,k)(i,j,k)使得这三个点距离相等。 解题思路 有两种情况,一是iii是j,kj,kj,k的祖先,二是i,j,ki,j,ki,j,k互相没有祖先关系 考虑…

初一级模拟试题总结(2019.3.2)

成绩 rank算上了其他大佬 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111lyflyflyf400400400100100100100100100100100100100100100111wjjwjjwjj280280280100100100808080000100100100111tjhtjhtjh200200200100100100000000100100100111fyfyfy200200200…

ASP.NET Core Razor生成Html静态文件

一、前言最近做项目的时候,使用Util进行开发,使用Razor写前端页面。初次使用感觉还是不大习惯,之前都是前后端分离的方式开发的,但是使用Util封装后的Angular后,感觉开发效率还是杠杠滴。二、问题在发布代码的时候&…

NEERC2017 Archery Tournament 线段树 新套路

题目链接 http://codeforces.com/gym/101630/attachments/download/6401/20172018-acmicpc-northeastern-european-regional-contest-neerc-17-en.pdf 题意 给出一些圆,这些圆圆心在x轴上方,且与x轴相切,任意时刻,不存在图上的…

P2178-[NOI2015]品酒大会【SA,并查集】

正题 题目链接:https://www.luogu.com.cn/problem/P2178 题目大意 长度为nnn的字符串,每个位置有一个权值。 如果对于q,pq,pq,p有sq,qr−1sp,pr−1s_{q,qr-1}s_{p,pr-1}sq,qr−1​sp,pr−1​那么就称q,pq,pq,p为rrr相似。 对于每个rrr求有多少对q,pq,pq,p是rrr相似…

【Floyed】【最短路】商店选址问题(ssl 1760)

商店选址问题 ssl 1760 题目大意: 有一些点,在一个点上按医院,有一个值就是这个点到其他点的最短路之和,问这个值最小是多少 原题: Description 给出一个城市的地图(用邻接矩阵表示)&…

一文看懂.NET的各种变体

曾几何时,我们只有一个.NET,叫作.NET Framework。如果想要开发.NET应用程序,只要使用.NET Framework即可,非常简单。几年之后,出现了.NET变种的寒武纪大爆发(我们称之为“.NET大爆炸”)&#xf…

Codeforces Gym - 100917 部分题解

A.Abstract Picture Gym - 100917A 分析:由于最后刷的一笔肯定使得某一行或者是某一列均为相同的颜色。 因此我们可以在一开始找到所有的行或者列,他们的颜色全都一样,把这样的行或列加入到队列里面去。 我们处理在队列里面的行或者列&…

【最短路】【Floyed】医院设置(ssl 1614)

医院设置 ssl 1614 题目大意: 有n个点,在一个点上安医院,使这个点到其他点的最短路之和最小 原题: Description 设有一棵二叉树(如右图)。其中,圈中的数字表示结点中居民的人口。圈边上数…

牛客练习赛69C-旅行【结论,最大生成树】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7329/C 题目大意 disx,ydis_{x,y}disx,y​表示x,yx,yx,y的所有路径的最短的边的最大值。 求一个1∼n1\sim n1∼n的排列,使得∑i2ndisi,i−1\sum_{i2}^ndis_{i,i-1}∑i2n​disi,i−1​最大 解题思路 首先一定是…

拓展 NLog 优雅的输送日志到 Logstash

在上上篇博客通过对aspnetcore启动前配置做了一些更改,以及对nlog进行了自定义字段,可以把请求记录输送到mysql,正式情况可能不会这么部署。因为近期也在学习elk,所以就打算做一个实例,结合nlog把日志输送到logstash&a…