在设计REST API或服务时,是否有任何已 Build 的最佳实践来处理安全性(身份验证,授权,身份管理)?
构建SOAP API时,您需要使用WS-Security作为指南,并且有很多关于该主题的文献 . 我发现有关保护REST endpoints 的信息较少 .
虽然我理解REST故意没有类似于WS- *的规范,但我希望出现最佳实践或推荐模式 .
任何讨论或相关文件的链接将非常感谢 . 如果重要的话,我们将使用WCF和POX / JSON序列化消息来构建使用.NET Framework v3.5构建的REST API /服务 .
18 回答
我搜索了很多关于restful ws安全性的信息,我们最终还是使用了来自客户端到服务器的令牌来验证请求 . 我使用spring security来授权服务中的请求,因为我必须根据已经在DB中的指定安全策略对每个请求进行身份验证和授权 .
OWASP(开放式Web应用程序安全项目)有一些备忘单,涵盖了Web应用程序开发的所有方面 . 该项目是非常有 Value 和可靠的信息来源 . 关于REST服务,您可以查看:https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
我曾经使用过OAuth几次,还使用了其他一些方法(BASIC / DIGEST) . 我全心全意地建议OAuth . 以下链接是我在使用OAuth时看到的最佳教程:
http://hueniverse.com/oauth/guide/
我在安全方面遇到的关于REST的最好的帖子之一就是1 RainDrop . 在Mix的MySpace API 's use OAuth also for security and you have full access to their custom channels in the RestChess code, which I did a lot of exploration with. This was demo' d,您可以找到发布here .
我会推荐OAuth 2/3 . 您可以在http://oauth.net/2/找到更多信息 .
这些答案中的每个人都忽略了真正的访问控制/授权 .
例如,如果您的REST API / Web服务是关于POSTing / GETing医疗记录,您可能需要定义访问控制策略,了解谁可以访问数据以及在何种情况下 . 例如:
医生可以获得与他们有照顾关系的患者的医疗记录
没有人可以在练习时间之外发布医疗数据(例如9到5)
最终用户可以获取他们拥有的医疗记录或他们作为监护人的患者的医疗记录
护士可以更新与护士属于同一单位的患者的医疗记录 .
为了定义和实现这些细粒度的授权,您需要使用一种名为XACML的基于属性的访问控制语言,即可扩展的访问控制标记语言 .
这里的其他标准如下:
OAuth:id . 联邦和授权授权,例如让服务代表我代理另一项服务(Facebook可以发布到我的Twitter)
SAML:身份联合/ Web SSO . SAML非常关注用户是谁 .
WS-Security / WS- *标准:这些标准专注于SOAP服务之间的通信 . 它们特定于应用程序级消息传递格式(SOAP),它们处理消息传递的各个方面,例如可靠性,安全性,机密性,完整性,原子性,事件......没有覆盖访问控制,所有都是特定于SOAP的 .
XACML与技术无关 . 它可以应用于Java应用程序,.NET,Python,Ruby ... Web服务,REST API等 .
以下是有趣的资源:
OASIS XACML website
NIST ABAC standard
我对客户端证书尚未提及SSL感到惊讶 . 当然,只有依靠证书识别的用户社区,这种方法才真正有用 . 但是许多政府/公司确实向用户发布了这些政府/公司 . 用户不必担心创建另一个用户名/密码组合,并且在每个连接上 Build 身份,因此与服务器的通信可以完全无状态,不需要用户会话 . (并不意味着所提到的任何/所有其他解决方案都需要会话)
对于Web应用程序安全性,您应该查看OWASP(https://www.owasp.org/index.php/Main_Page),它提供各种安全攻击的备忘单 . 您可以采用尽可能多的措施来保护您的应用程序 . 关于API安全性(授权,身份验证,身份管理),已经提到了多种方式(Basic,Digest和OAuth) . OAuth1.0中存在循环漏洞,因此您可以使用OAuth1.0a(由于担心规范,OAuth2.0未被广泛采用)
由于@Nathan最终得到了一个简单的HTTP Header,有些人说过OAuth2和客户端SSL证书 . 它的要点是......你的REST API不应该处理安全性,因为它应该超出API的范围 .
相反,应该将安全层置于其上,无论它是否为HTTPWeb代理背后的 Headers (像SiteMinder,Zermatt甚至是Apache HTTPd这样的常见方法),或者像OAuth 2一样复杂 .
关键是请求应该在没有任何最终用户交互的情况下工作 . 所需要的只是确保与REST API的连接经过身份验证 . 在Java EE中,我们可以在
HttpServletRequest
上获得userPrincipal
的概念 . 它还在部署描述符中管理,URL模式可以是安全的,因此REST API代码不再需要检查 .在WCF世界中,我将使用
ServiceSecurityContext.Current
来获取当前的安全上下文 . 您需要将应用程序配置为要求身份验证 .我上面的语句有一个例外,那就是使用nonce来防止重放(可能是攻击或只是两次提交相同数据的人) . 该部分只能在应用程序层中处理 .
正如tweakt所说,亚马逊S3是一个很好的模型 . 他们的请求签名确实具有一些功能(例如合并时间戳),有助于防止意外和恶意请求重放 .
HTTP Basic的优点在于几乎所有HTTP库都支持它 . 当然,在这种情况下,您需要要求SSL,因为通过网络发送明文密码几乎是一件坏事 . 使用SSL时,Basic优于Digest,因为即使调用者已经知道需要凭据,Digest也需要额外的往返来交换nonce值 . 使用Basic,呼叫者只需在第一次发送凭据 .
一旦 Build 了客户端的身份,授权实际上只是一个实现问题 . 但是,您可以使用现有授权模型将授权委派给其他组件 . 关于Basic的优点还在于您的服务器最终会得到客户端密码的纯文本副本,您可以根据需要将其简单地传递到基础架构中的另一个组件 .
已经有一段时间了,但问题仍然存在,尽管答案可能会有所改变 .
API网关将是一种灵活且高度可配置的解决方案 . 我测试并使用了KONG非常喜欢我所看到的 . KONG提供了自己的管理REST API,您可以使用它来管理用户 .
Express-gateway.io是最新的,也是API网关 .
在Github上找到了一个很棒的清单:
Authentication
不要在身份验证,令牌生成,密码存储中重新发明轮子 . 使用标准 .
在登录中使用
Max Retry
和jail功能 .对所有敏感数据使用加密 .
JWT (JSON Web Token)
使用随机复杂的密钥(JWT Secret)来强制执行令牌非常困难 .
不要从有效负载中提取算法 . 强制算法在后端(HS256或RS256) .
使令牌过期(
TTL
,RTTL
)尽可能短 .不要将敏感数据存储在
JWT
有效载荷中,可以轻松解码 .OAuth
始终验证
redirect_uri
服务器端以仅允许列入白名单的URL .始终尝试交换代码而不是令牌(不允许
response_type=token
) .使用带有随机哈希的state参数来阻止
OAuth
认证过程中的CSRF
.定义默认范围,并验证每个应用程序的范围参数 .
Access
限制请求(限制)以避免DDoS /暴力攻击 .
在服务器端使用HTTPS以避免MITM(中间人攻击)
使用带SSL的
HSTS
标头可避免SSL Strip攻击 .Input
根据操作使用正确的HTTP方法:
GET
(读取),POST
(创建),PUT/PATCH
(替换/更新)和DELETE
(删除记录),如果请求的方法不适合,则使用405 Method Not Allowed
进行响应请求的资源 .根据请求
Accept
Headers (内容协商)验证内容类型,以仅允许您支持的格式(例如application/xml
,application/json
等),如果不匹配则回复406 Not Acceptable
响应 .在接受时验证发布数据的
content-type
(例如application/x-www-form-urlencoded
,multipart/form-data
,application/json
等) .验证用户输入以避免常见漏洞(例如XSS,SQL注入,远程执行代码等) .
不要在URL中使用任何敏感数据(凭据,密码,安全令牌或API密钥),而是使用标准
Authorization
标头 .使用API网关服务启用缓存,
Rate Limit
策略(例如,配额,尖峰逮捕,并发速率限制)并动态部署API资源 .Processing
检查所有 endpoints 是否受到身份验证后的保护,以避免身份验证过程中断 .
应避免用户自己的资源ID . 使用/ me / orders而不是/ user / 654321 / orders .
不自动增加ID . 请改用UUID .
如果要解析XML文件,请确保未启用实体解析以避免XXE(XML外部实体攻击) .
如果要解析XML文件,请确保未启用实体扩展以避免通过指数实体扩展攻击导致Billion Laughs / XML炸弹 .
使用CDN进行文件上传 .
如果您正在处理大量数据,请使用Workers和Queues在后台尽可能多地处理并快速返回响应以避免HTTP阻塞 .
不要忘记关闭 DEBUG 模式 .
Output
发送
X-Content-Type-Options: nosniff
Headers .发送
X-Frame-Options: deny
Headers .发送
Content-Security-Policy: default-src 'none'
Headers .删除指纹 Headers -
X-Powered-By
,Server
,X-AspNet-Version
等 .强制
content-type
为您的回复,如果您返回application/json
,那么您的回复内容类型为application/json
.不要返回凭据,密码,安全令牌等敏感数据 .
根据完成的操作返回正确的状态代码 . (例如
200 OK
,400 Bad Request
,401 Unauthorized
,405 Method Not Allowed
等) .我想添加(与stinkeymatt一致),最简单的解决方案是将SSL证书添加到您的站点 . 换句话说,请确保您的网址是HTTPS:// . 这将涵盖您的运输安全(砰的一声) . 使用RESTful url,想法是保持简单(与WS * security / SAML不同),您可以使用oAuth2/openID connect甚至Basic Auth(在简单情况下) . 但是你仍然需要SSL / HTTPS . 请在此处检查ASP.NET Web API 2安全性:http://www.asp.net/web-api/overview/security(文章和视频)
除HTTP之外,没有REST标准 . 那里有成熟的REST服务 . 我建议你看看他们,并了解他们的工作方式 .
例如,我们在开发自己的S3 REST服务时借用了很多想法 . 但我们选择不使用基于请求签名的更高级的安全模型 . 更简单的方法是基于SSL的HTTP Basic身份验证 . 你必须决定什么在你的情况下最有效 .
另外,我强烈推荐O'reilly的书RESTful Web Services . 它解释了核心概念,并提供了一些最佳实践 . 您通常可以使用他们提供的模型并将其映射到您自己的应用程序 .
SOAP世界很好地涵盖了安全标准这一事实在默认情况下并不安全 . 首先,标准是复杂的 . 复杂性不是安全性的好朋友,而XML signature wrapping attacks等实施漏洞在这里很常见 .
至于.NET环境,我帮不了多少,但“Building web services with Java”(一个有~10位作者的砖块)确实帮助我理解了WS- *安全架构,特别是它的怪癖 .
REST本身没有提供安全标准,但OAuth和SAML之类的东西正迅速成为这一领域的标准 . 但是,身份验证和授权只是您需要考虑的一小部分 . 许多与Web应用程序相关的已知漏洞都非常适用于REST apis . 您必须考虑输入验证,会话破解,不适当的错误消息,内部员工漏洞等 . 这是一个很大的主题 .
感谢您的出色建议 . 我们最终使用自定义HTTP标头将身份令牌从客户端传递到服务,以准备将我们的RESTful API与即将推出的Microsoft的Zermatt Identity框架集成 . 我已经描述了问题here和我们的解决方案here . 我也提出了_213244的建议并购买了RESTful Web Services - 如果您正在构建任何类型的RESTful API,这本书非常好 .
您可能还想看看OAuth,这是一种新兴的基于令牌授权的开放式协议,专门针对http apis .
它与flickr和remember the milk "rest" apis采用的方法非常相似(不一定是restful apis的好例子,但是基于令牌的方法的好例子) .