注册表 REST API 最佳实践

Registration Form REST API Best Practices

我正在使用 MEAN 堆栈构建 SaaS 应用程序,有几个关于如何最好地保护注册表的问题。 Express.js 是我用来生成端点的(通过 angular-fullstack)

我 "tenants" 使用注册表(姓名、电子邮件、密码等)进行注册。此 REST API 当前不安全(POST /tenants)。

我的问题是:

  1. 我应该以某种方式保护这个 POST 吗?如果是,怎么做?
  2. 如果我不保护 POST /tenants 端点,我该如何避免有人编写脚本来创建一大堆租户并攻击我的应用程序?
  3. 我想使用某种确认电子邮件,但这是注册新租户时的好做法吗?

我很想在这里得到一些关于如何最好地进行的反馈。

谢谢!

您应该查看开放 Web 应用程序安全项目 (OWASP) website and their Top 10 vulnerabilities thoroughly. There's a lot of information there. I also recommend abiding by their cheat sheets。此资源是一个有用的起点。 Web 安全很复杂,需要您的保护方案全面。

reCAPTCHA 是我选择用来解决同样问题的解决方案。

引用 Google's developer site on reCAPTCHA 将 reCAPTCHA 集成到站点的概述。值得注意的是 Google 的 reCAPTCHA 代码实验室还包含 Java.

的示例

Overview

To start using reCAPTCHA, you need to sign up for an API key pair for your site. The key pair consists of a site key and secret key. The site key is used to invoke reCAPTCHA service on your site or mobile application. The secret key authorizes communication between your application backend and the reCAPTCHA server to verify the user's response. The secret key needs to be kept safe for security purposes.

First, choose the type of reCAPTCHA and then fill in authorized domains or package names. After you accept our terms of service, you can click Register button to get new API key pair.

Now please take the following steps to add reCAPTCHA to your site or mobile application:

  1. Choose the client side integration:
  2. Verifying the user's response

作为 Python 粉丝,这是我在 Django 中实现此解决方案所遵循的示例(参考:Google's codelab example):

1. Getting set up

Install and verify web server

This codelab can either be run locally or through the gcloud shell in Google Cloud Platform. To get started with the gcloud shell go to https://console.cloud.google.com/appengine/start.

Download the Code

Clone all the code for this codelab:

git clone https://github.com/googlecodelabs/recaptcha-codelab.git

For Python:

cd recaptcha-codelab/phase1-python
python server.py

In the web browser, go to http://localhost:8080 to see the example UI without reCAPTCHA integrated.

2. Registering with the reCAPTCHA Admin Console

... We recommend if you have time that you follow through and create your own registration in the admin console. Before you use reCAPTCHA in development or production you will need to do this step.

First go to The reCAPTCHA Admin Site.

Choose ‘Invisible reCAPTCHA' as the type of captcha.

Fill in the list of domains you wish to show your captcha. The reCAPTCHA site key you create will only work on these domains. Save the site key and secret key for the later stages.

3. Add Invisible reCAPTCHA to the frontend - Python

Let's update the frontend to call Invisible reCAPTCHA with your favorite text editor.

First let's add a script tag to the html element in feedback.html.

feedback.html

 <html>
 <head>
   <title>Suggestion page</title>
   <script src='https://www.google.com/recaptcha/api.js'></script>

Now update the attributes to the submit button. Add class='g-recaptcha' data-sitekey="YOUR SITE KEY" and add a data-callback.

feedback.html

     <button class="g-recaptcha"
       data-sitekey="6LfeHx4UAAAAAAKUx5rO5nfKMtc9-syDTdFLftnm"
       data-callback="onSubmit">Submit</button>

The full file should be:

feedback.html

<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
  <title>Suggestion page</title>
  <script src='https://www.google.com/recaptcha/api.js'></script>
  <script>
    function onSubmit() {
      document.getElementById("demo-form").submit();
    }   
  </script>
  <style>
    body {
      font-family: Helvetica, sans-serif;
    }   
    .status-message {
      background-color: #5ff;
      margin-bottom: 10px;
      text-align: center;
    }   
    textarea {
      margin: 10px 0;
      resize: none;
    }   
  </style>
</head>
<body>
  <h3>Give us feedback on our webpage!</h3>
  <div class="status-message">%s</div>
  <form id="demo-form" action="/feedback" method="POST">
    Your comment <br><textarea name="feedback" cols="50" rows="5"></textarea><br>
    <!-- Replace this with your site key --> 
    <button class="g-recaptcha"
            data-sitekey="6LfeHx4UAAAAAAKUx5rO5nfKMtc9-syDTdFLftnm"
            data-callback="onSubmit">Submit</button>
  </form>
</body>
</html>

3. Validate the Invisible reCAPTCHA on the Server - Python

In "Registering with the reCAPTCHA Admin Console" we created a new site key. As part of that process a site secret was created. The site secret is necessary to validate the CAPTCHA solution. For the purposes of this code lab you can use the default keys provided. These will only work on localhost.

The validation of the reCAPTCHA token is done by sending a POST request to https://www.google.com/recaptcha/api/siteverify. The details are in Verifying the user's response.

To validate the reCAPTCHA token, let's update the server. First we need to add the site secret and site verify constants.

server.py

SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify'
SITE_SECRET = '6LfeHx4UAAAAAFWXGh_xcL0B8vVcXnhn9q_SnQ1b'
RECAPTCHA_RESPONSE_PARAM = 'g-recaptcha-response'

Then we need to update our POST handler to verify the token.

server.py

def do_POST(self):
    self.set_headers();
    post_body = parse_qs(self.rfile.read(int(self.headers['Content-Length'])))

    success = False
    if RECAPTCHA_RESPONSE_PARAM in post_body:
      token = post_body[RECAPTCHA_RESPONSE_PARAM][0]
      resp = urllib.urlopen(
          SITE_VERIFY_URL, urllib.urlencode(
              {'secret': SITE_SECRET, 'response': token}, True)).read()
      if json.loads(resp).get("success"):
        success = True

    if success:
      message = 'Thanks for the feedback!'
    else:
      message = 'There was an error.'
    self.wfile.write(open(curdir + sep + 'feedback.html').read() % message)

The final file should look like this:

server.py

import json
import urllib
from os import curdir, sep
from urlparse import parse_qs
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify'
SITE_SECRET = '6LfeHx4UAAAAAFWXGh_xcL0B8vVcXnhn9q_SnQ1b'
RECAPTCHA_RESPONSE_PARAM = 'g-recaptcha-response'

class Handler(BaseHTTPRequestHandler):
  def set_headers(self):
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()

  def do_GET(self):
    self.set_headers();
    self.wfile.write(open(curdir + sep + 'feedback.html').read() % '')

  def do_POST(self):
    self.set_headers();
    post_body = parse_qs(self.rfile.read(int(self.headers['Content-Length'])))

    success = False
    if RECAPTCHA_RESPONSE_PARAM in post_body:
      token = post_body[RECAPTCHA_RESPONSE_PARAM][0]
      resp = urllib.urlopen(
          SITE_VERIFY_URL, urllib.urlencode(
              {'secret': SITE_SECRET, 'response': token}, True)).read()
      if json.loads(resp).get("success"):
        success = True

    if success:
      message = 'Thanks for the feedback!'
    else:
      message = 'There was an error.'
    self.wfile.write(open(curdir + sep + 'feedback.html').read() % message)

if __name__ == '__main__':
  httpd = HTTPServer(('', 8080), Handler)
  httpd.serve_forever()

You're all done! Now reload the server and give it a try. The completed version can be found in final-python/server.py. You now have a basic integration with reCAPTCHA to protect your form. In the background, we are verifying the user and will sometimes show a reCAPTCHA challenge to make sure that your website is protected from abuse. More details and options can be found on our developer site.

请注意:我是一名独立的软件开发人员,与 Google 没有任何关系。