安全的 RESTful API,可供 Web 应用程序(angular)、iOS 和 Android 使用 [英] Secured RESTful API that can be used by Web App (angular), iOS and Android

查看:35
本文介绍了安全的 RESTful API,可供 Web 应用程序(angular)、iOS 和 Android 使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须制定一个计划来开发一个 RESTful API(Python/Flask),我们未来的网络应用(Angularjs)和移动应用(iOS/Android)可以使用它.

我研究了三天,遇到了几个场景:使用 HTTPS 是以下方法的一种,以使其更安全.但是 https 速度较慢,这可能意味着我们需要更快、更昂贵的服务器.

  1. 使用 Basic-Http-Auth 并为每个 API 请求通过网络以纯格式(但为 https)发送用户名/密码.
  2. 使用 Digest-Auth,它是密码的散列,跟踪将是自动的 这适用于网络应用程序,但是我无法确认 iPhone 和 Android 是否会在本机支持此功能.如果他们这样做,那可能是一个简单的解决方案!
  3. 使用自定义 http 标头,我将在成功验证后在 http 标头中发送自定义 Auth 字符串.但是,我必须确保为用户发出的每个请求都发送此身份验证代码.这使它与 1) 完全一样,不同之处在于不使用普通密码并且授权码可以在没有任何风险的情况下过期.同样有问题的是验证代码的跟踪,它不再像 2) 中那样自动化
  4. 使用 OAuth 是一种选择.但设置起来相当困难.如果没有更好的方法,也许这就是唯一的方法?
  5. 按照此好文章.简而言之,他说服务器和客户端都知道一个私钥,他们将用它来散列通信.这就像黑帮握手一样,你只会相信送货员,如果他知道黑帮握手.再往下是有人问的评论:

<块引用>

如何在纯 HTML5 应用程序中保持私钥安全"?

你说得对;在纯 HTML5 (JS/CSS/HTML) 应用程序中,没有保护密钥.你会做所有的沟通HTTPS 在这种情况下您不需要密钥,因为您可以安全地使用标准 API_KEY 或其他一些友好的方式识别客户端不需要 HMAC 或 HMAC 的复杂性的标识符.

所以换句话说,首先将这种方法用于网络应用程序是没有意义的.老实说,我也不明白这应该如何在移动设备上工作.用户下载了我们的应用程序,我如何将私钥从 iphone 发送到服务器?一传送,就被破解了.

我研究得越多,我就越犹豫不决.

我想问问以前做过这件事的专业人士,可以分享他们的经验.非常感谢

解决方案

您似乎将两个不同的概念混淆/合并在一起.我们首先讨论加密流量 (HTTPS),然后我们开始讨论管理经过身份验证的会话的不同方法.在安全应用程序中,这些不是相互排斥的任务.似乎还可能存在对会话管理如何影响身份验证的误解.在此基础上,我将介绍 Web 应用程序/Web api 会话管理、身份验证和加密.

简介

会话管理

HTTP 事务默认是无状态的.HTTP 没有指定任何方法让您的应用程序知道 HTTP 请求已从特定用户发送(是否经过身份验证).

对于健壮的 Web 应用程序,这是不可接受的.我们需要一种方法来关联跨多个请求发出的请求和数据.为此,在向服务器发出初始请求时,需要为用户分配一个会话".通常,会话具有某种发送给客户端的唯一 ID.客户端随每个请求发送该会话 ID,服务器使用每个请求中发送的会话 ID 为用户正确准备响应.

重要的是要记住会话 ID"可以被称为许多其他东西.其中一些示例是:会话令牌、令牌等.为了保持一致性,我将在此响应的其余部分使用会话 ID".

来自客户端的每个 HTTP 请求都需要包含会话 ID;这可以通过多种方式完成.流行的例子是:

  1. 它可以存储在 cookie 中 - 当前域的 cookie 会在每次请求时自动发送.
  2. 可以在 URL 上发送 - 每个请求都可以在 URL 上发送会话 ID,不建议使用,因为会话 ID 将保留在客户端历史记录中
  3. 它可以作为 HTTP 标头发送 - 每个请求都需要指定标头

大多数 Web 应用程序框架都使用 cookie.然而,依赖 JavaScript 和单页设计的应用程序可能会选择使用 HTTP 标头/将其存储在服务器可观察到的其他位置.

请务必记住,通知客户端其会话 ID 的 HTTP 响应和包含会话 ID 的客户端请求是完全纯文本且 100% 不安全的.为了解决这个问题,所有 HTTP 流量都需要加密;这就是 HTTPS 的用武之地.

还需要指出的是,我们还没有讨论将会话链接到我们系统中的特定用户.会话管理只是将数据与访问我们系统的特定客户端相关联.客户端可以处于已认证和未认证两种状态,但在这两种状态下,它们通常都有一个会话.

身份验证

身份验证是我们将会话链接到系统中特定用户的地方.这通常由用户提供凭据的登录过程处理,这些凭据经过验证,然后我们将会话链接到我们系统中的特定用户记录.

用户又通过访问控制列表和访问控制条目(ACL 和 ACE)与细粒度访问控制的权限相关联.这通常称为授权".大多数系统总是同时具有身份验证和授权.在一些简单的系统中,所有经过身份验证的用户都是平等的,在这种情况下,您将无法通过简单身份验证获得授权.关于这方面的更多信息超出了本问题的范围,但请考虑阅读有关 ACE/ACL 的内容.

可以用不同的方式将特定会话标记为代表经过身份验证的用户.

  1. 他们存储在服务器端的会话数据可以存储他们的用户 ID/一些其他标志,表示使用已被验证为特定用户
  2. 另一个用户令牌可以像会话 ID 一样发送到客户端(通过未加密的 HTTP 发送与发送未加密的会话 ID 一样不安全)

两种选择都可以.这通常归结为您所使用的技术以及它们默认提供的内容.

客户端通常会启动身份验证过程.这可以通过将凭据发送到特定 url(例如 yoursite.com/api/login)来完成.但是,如果我们想要RESTful",我们通常会通过某个名词引用资源并执行创建"操作.这可以通过要求将凭据 POST 到 yoursite.com/api/authenticatedSession/来完成.想法是创建一个经过身份验证的会话.大多数站点只是将凭据发布到/api/login 等.这与真正的"或纯粹的"RESTful 理想背道而驰,但大多数人认为这是一个更简单的概念,而不是将其视为创建经过身份验证的会话".

加密

HTTPS 用于加密客户端和服务器之间的 HTTP 流量.在依赖已认证和未认证用户的系统上,所有依赖于已认证用户的流量都需要通过 HTTPS 进行加密;没有办法解决这个问题.

这样做的原因是,如果您对用户进行身份验证,与他们共享一个秘密(他们的会话 ID 等),然后开始在纯 HTTP 中展示该秘密,他们的会话可能会被中间人劫持攻击.黑客将等待流量通过观察到的网络并窃取机密(因为它是通过 HTTP 的纯文本),然后假装是原始客户端启动与您的服务器的连接.

人们解决这个问题的一种方法是将请求的远程 IP 地址与经过身份验证的会话相关联.这单独是无效的,因为任何黑客都能够在他们的虚假请求中欺骗他们的请求远程 IP 地址,然后观察您的服务器发回的响应.大多数人会争辩说,除非您正在跟踪历史数据并使用它来识别特定用户的登录模式(就像 Google 所做的那样),否则这甚至不值得实施.

如果您需要在 HTTP 和 HTTPS 部分之间拆分您的站点,则 HTTP 流量必须不发送或接收会话 ID 或用于管理用户身份验证状态的任何令牌.同样重要的是不要在非 HTTPs 请求/响应中发送敏感的应用程序数据.

在网络应用程序/API 中保护数据的唯一方法是加密您的流量.

你的话题一个接一个

基本-Http-Auth

  • 身份验证:是
  • 会话管理:否
  • 加密:否

这是一种仅通过网络资源进行身份验证的方法.基本身份验证通过 URL 标识的资源对使用进行身份验证.这是最流行的 Apache HTTP Web 服务器使用基于 .htaccess 的目录/位置身份验证实现的.凭据必须随每个请求一起发送;客户端通常会为用户透明地处理此问题.

其他系统可以使用基本身份验证作为身份验证模式.但是,使用 Basic-Http-Auth 的系统提供身份验证和会话管理,而不是 Basic-Http-Auth 本身.

  • 这不是会话管理.
  • 这不是加密;内容和凭据几乎是 100% 纯文本
  • 这不会保护应用程序的 HTTP 请求/响应的内容.

摘要验证

  • 身份验证:是
  • 会话管理:否
  • 加密:否

这与 Basic-Http-Auth 完全相同,只是添加了一些简单的 MD5 摘要.不应该依赖这种消化而不是使用加密.

  • 这不是会话管理.
  • 这不是加密;摘要很容易被破坏
  • 这不会保护应用程序的 HTTP 请求/响应的内容.

OAuth

  • 身份验证:是
  • 会话管理:否
  • 加密:否

OAuth 只是让您有一个外部服务验证凭据.之后,由您来管理/处理向您的 OAuth 提供商发出的身份验证请求结果.

  • 这不是会话管理.
  • 这不是加密;您的网站流量仍然是纯文本.由于 HTTPS 限制,身份验证过程将是安全的,但您的应用程序仍然容易受到攻击.
  • 这不会保护应用程序的 HTTP 请求/响应的内容.

Gangster Handshake/自定义 HTTP 标头

  • 身份验证:是的,可能
  • 会话管理:是的,可能
  • 加密:否

Custom HTTP header"是一种Gangster Handshakes";因此,我将使用同一部分来讨论它们.唯一的区别是自定义 HTTP 标头"指定 hanshake(会话 ID、令牌、用户身份验证令牌等)的存储位置(即在 HTTP 标头中).

重要的是要注意,这些没有指定如何处理身份验证,也没有指定如何处理会话管理.它们本质上描述了会话 ID/身份验证令牌的存储方式和位置.

身份验证需要由您的应用程序或通过第三方(例如 OAuth)处理.会话管理仍然需要实施.有趣的是,如果您愿意,您可以选择将两者合并.

  • 这不是加密;您的网站流量仍然是纯文本.如果您使用 OAuth,由于 HTTPS 限制,身份验证过程将是安全的,但您的应用程序仍然容易受到攻击.
  • 这不会保护应用程序的 HTTP 请求/响应的内容.

你需要做什么

...我强烈建议您确保您了解一个强大且安全的 Web 应用程序需要以下内容:

  1. 加密(HTTPS 几乎是您唯一的选择)
  2. 会话管理
  3. 身份验证/授权

授权依赖于身份验证.身份验证依赖于会话管理和加密,可确保会话不会被劫持,并且凭据不会被拦截.

烧瓶登录

我认为您应该研究 flask-login 作为避免重新实现轮子的一种方式.我个人从未使用过它(我在 python 中使用金字塔作为 web 应用程序).但是,我之前在 web application/python board 中看到过它.它处理身份验证和会话管理.通过 HTTPS 抛出您的 Web api/应用程序,您将拥有所有三个(加密、会话管理和用户身份验证).

如果您不/不能使用flask-login,请准备好自己编写,但首先要研究如何创建安全的身份验证机制.

如果可能的话,如果您不了解如何编写身份验证程序,请先了解黑客如何使用基于模式的攻击、定时攻击等,请不要尝试.

请加密您的流量

...不再认为您可以通过一些聪明的"令牌使用来避免使用 HTTPS.摒弃您应该避免使用 HTTPS/加密的想法,因为它很慢"、进程密集等.它是进程密集的,因为它是一种加密算法.确保用户数据和应用程序数据安全的需求应始终是您的首要任务.您不想经历通知用户他们的数据已被泄露的恐怖经历.

I have to lay out a plan to develop a RESTful API (Python/Flask) that could be used by our future web app (Angularjs) and mobile apps (iOS/Android).

I have been researching for three days and have come across several scenarios: Using HTTPS is one way on top of the methods below to keep it safer. But https is slower, which could mean we need faster and more expensive servers.

  1. Using Basic-Http-Auth and sending username/password in plain (yet https) over the wire for every request to the API.
  2. Using Digest-Auth, which is a hash of the password and the tracking would be automatic This would work for the web app, however I wasn't able to confirm if iPhones and Android would support this natively. If they do, that could be an easy solution!
  3. Using a custom http header, where I would send a custom Auth string in http header upon a successful authentication. But then I have to make sure I am sending this auth code for every request that the user makes. This makes it exactly like 1) with the difference that plain passwords aren't used and the auth code can expire without any risk. Also problematic is the tracking of the auth code, which is no longer automated as in 2)
  4. Using OAuth is an option. But its quite difficult to set up. If there is no better way, maybe thats the only way?
  5. Securing the API like Amazon S3 as described in this great article. In short, he says that both server and client would know of a private key, which they would use to hash the communication. It will be like gangster handshake, that you only would trust the delivery boy, if he knows the gangsta handshake. Further down the comments someone asks:

How to keep the private key "secure" in a pure HTML5 app ?

You are exactly right; in a pure HTML5 (JS/CSS/HTML) app, there is no protecting the key. You would do all communication over HTTPS in which case you wouldn’t need a key since you could safely identify a client using a standard API_KEY or some other friendly identifier without the need or complexity of an HMAC.

So in other words there is even no point of using the method for an web app in first place. And honestly I don't understand how this should work on the mobile device either. A user downloads our app and how do I send the private key from the iphone to the server? The moment I transferred it, it will be compromised.

The more I am researching the more indecisive I am getting.

I was hoping to ask some pros who have done this previously and could share their experience. Many Thanks

解决方案

You seem to be confusing/merging two different concepts together. We start of talking about encrypting traffic (HTTPS) and then we start talking about different ways to manage authenticated sessions. In a secure application these are not mutually exclusive tasks. There also seem to potentially be a misunderstanding how session management can impact authentication. Based on that I will provide a primer on web application/web api session management, authentication, and encryption.

Introduction

Session Management

HTTP transactions are stateless by default. HTTP does not specify any method to let your application know that a HTTP request has been sent from a specific user (authenticated or not).

For robust web applications, this is not acceptable. We need a way to associate requests and data made across multiple requests. To do this, on initial request to the server a user needs to be assigned a "session". Generally sessions have some kind of unique id that is sent to the client. The client sends that session id with every request and the server uses the session id sent in every request to properly prepare a response for the user.

It is important to remember that a 'session id' can be called many other things. Some examples of those are: session token, token, etc. For consistency I will use 'session id' for the rest of this response.

Each HTTP request from the client needs to include the session id; this can be done in many ways. Popular examples are:

  1. It can be stored in a cookie - cookies for the current domain are automatically sent on every request.
  2. It can be sent on the URL - each request could send the session id on the URL, not suggested since session ids will stay in the clients history
  3. It can be sent via as a HTTP header - each request would need to specify the header

Most web application frameworks use cookies. However application that rely on JavaScript and single page designs may opt to use a HTTP header/store it in some other location that is observable by the server.

It is very important to remember that the HTTP response that notifies the client of their session id and the client's requests that contain the session id are completely plain text and 100% unsafe. To battle that, all HTTP traffic needs to be encrypted; that is where HTTPS comes in.

It is also important to point out we have not talked about linking a session to a specific user in our system. Session management is just associating data to a specific client accessing our system. The client can be in both authenticated and unauthenticated states, but in both states they generally have a session.

Authentication

Authentication is where we link a session to a specific user in our system. This is generally handled by a login process where a user supplies credentials, those credentials are verified, and then we link a session to a specific user record in our system.

The user is in turn associated with privileges for fine grained access control via access control lists and access control entries (ACL and ACE). This is generally referred to as "Authorization". Most system always have both Authentication and Authorization. In some simple systems all authenticated users are equals in which case you won't have authorization past simple authentication. Further information on this is out of scope for this question, but consider reading about ACE/ACL.

A specific session can be flagged as representing an authenticated user in different ways.

  1. Their session data stored server side could store their user id / some other flag that denotes that the use is authenticated as a specific user
  2. Another user token could be send to the client just like a session id (which over unencrypted HTTP is just as unsafe as sending a session id unencrypted)

Either option is fine. It generally comes down to the technology you are working in and what they offer by default.

A client generally initiates the authentication process. This can be done by sending credentials to a specific url (e.g. yoursite.com/api/login). However if we want to be 'RESTful' we generally would referencing a resource by some noun and doing the action of 'create'. This could be done by requiring a POST of the credentials to yoursite.com/api/authenticatedSession/. Where the idea would be to create an authenticated session. Most sites just POST the credentials to /api/login or the like. This is a departure from "true" or "pure" RESTful ideals, but most people find this a simpler concept rather than thinking of it as "creating an authenticated session".

Encryption

HTTPS is used to encrypt HTTP traffic between a client and server. On a system that relies on authenticated and unauthenticated users, all traffic that relies on a user being authenticated needs to be encrypted via HTTPS; there is no way around this.

The reason for this is that if you authenticate a user, share a secret with them (their session id, etc) and then begin to parade that secret in plain HTTP their session can be hijacked by man-in-the-middle attacks. A hacker will wait for for the traffic to go through an observed network and steal the secret (since its plain text over HTTP) and then initiate a connection to your server pretending to be the original client.

One way people combat this is by associating the requests remote IP address to an authenticated session. This is ineffective alone as any hacker will be able to spoof their requests remote IP address in their fake requests and then observe the responses your sever is sending back. Most would argue that this is not even worth implementing unless you are tracking historical data and using it to identify a specific user's login patterns (like Google does).

If you need to split up your site between HTTP and HTTPS sections, it is imperative that the HTTP traffic does not send or receive the session id or any token used to manage the authentication status of a user. It is also important that you do not send sensitive application data within non-HTTPs requests/responses.

The only way to secure data within web applications/APIs is to encrypt your traffic.

Your Topics One By One

Basic-Http-Auth

  • Authentication: YES
  • Session Management: NO
  • Encryption: NO

This is a method for authenticating by web resource only. Basic authentication authenticates uses by resource identified by URL. This was most popularly implemented by Apache HTTP Web Server with the use of .htaccess based directory/location authentication. Credentials have to be sent with each request; clients generally handled this transparently for users.

Basic authentication can be used by other systems as a mode of authentication. However, the systems that utilize Basic-Http-Auth are providing authentication and session management, not the Basic-Http-Auth itself.

  • This is not session management.
  • This is not encryption; content and credentials are nearly 100% plain text
  • This does not secure the contents of the application's HTTP request/responses.

Digest-Auth

  • Authentication: YES
  • Session Management: NO
  • Encryption: NO

This is exactly the same as Basic-Http-Auth with the addition of some simple MD5 digesting. This digesting should not be relied upon instead of using encryption.

  • This is not session management.
  • This is not encryption; the digest is easily broken
  • This does not secure the contents of the application's HTTP request/responses.

OAuth

  • Authentication: YES
  • Session Management: NO
  • Encryption: NO

OAuth just lets you have an external service validate credentials. After that it is up to you to manage/work with the result of authentication request to your OAuth provider.

  • This is not session management.
  • This is not encryption; your sites traffic is still plain text. The authentication process will be secure due to HTTPS restrictions, but your application is still vulnerable.
  • This does not secure the contents of the application's HTTP request/responses.

Gangster Handshake / Custom HTTP header

  • Authentication: YES, potentially
  • Session Management: YES, potentially
  • Encryption: NO

"Custom HTTP header" is a type of "Gangster Handshakes"; as such I will use the same section to discuss them. The only difference is that a "Custom HTTP header" is specifying where the hanshake (session id, token, user authentication toke, etc) will be stored (i.e. in a HTTP header).

It is important to note that these do not specify how authentication will be handled, nor do they specify how session management will be handled. They essentially describe how and where session ids/authentication tokens will be stored.

Authentication would need to be handled by your application or via a third party (e.g. OAuth). Session management will still need to be implemented as well. The interesting thing is you can choose the merge the two if you wish.

  • This is not encryption; your sites traffic is still plain text. The authentication process will be secure due to HTTPS restrictions if you use OAuth, but your application is still vulnerable.
  • This does not secure the contents of the application's HTTP request/responses.

What You Need To Do

...I highly suggest you make sure that you understand that a robust web application that is secure needs the following:

  1. Encryption (HTTPS is pretty much your only choice)
  2. Session Management
  3. Authentication / Authorization

Authorization relies upon Authentication. Authentication relies upon Session Management and Encryption makes sure the session isn't hijacked and that the credentials are not intercepted.

Flask-Login

I think you should look into flask-login as a way to avoid re-implementing the wheel. I have personally never used it (I use pyramid for web applications in python). However, I have seen it mentioned before in web application/python boards. It handles both authentication and session management. Throw your web api/application through HTTPS and you have all three (Encryption, Session Management, and User Authentication).

If you do not / can not use flask-login, be prepared to write your own, but do research first on how to create secure authentication mechanisms.

If at all possible, if you do not understand how to write an authentication procedure please do not attempt it without first learning how hackers use pattern based attacks, timing attacks, etc.

Please Encrypt Your Traffic

...move past the idea that you can avoid using HTTPS with some "clever" token use. Move past the idea that you should avoid using HTTPS/encryption because "its slow", process intensive, etc. It is process intensive because it is an encryption algorithm. The need to ensure the safety of your user's data and your applications data should always be your highest priority. You do not want to go through the horror of notifying your users that their data was compromised.

这篇关于安全的 RESTful API,可供 Web 应用程序(angular)、iOS 和 Android 使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆