python - 安全的 Python REST API

标签 python rest authentication flask

我正在尝试用 python 编写一些 REST API,首先我开始编写 Authenticate 代码。我在其中一个网站上找到了用于身份验证的示例代码:

from functools import wraps
from flask import request, Response

def check_auth(username, password):
    """This function is called to check if a username /
    password combination is valid.
    """
    return username == 'admin' and password == 'secret'

def authenticate():
    """Sends a 401 response that enables basic auth"""
    return Response(
    'Could not verify your access level for that URL.\n'
    'You have to login with proper credentials', 401,
    {'WWW-Authenticate': 'Basic realm="Login Required"'})

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(username, password):
            return authenticate()
        return f(*args, **kwargs)
    return decorated

我已经使用上面的代码来保护我的示例应用程序:

@app.route('/student/<studentid>', methods = ['GET'])
@requires_auth
def api_users(studentid):
    students = {'1':'ABC', '2':'XYZ', '3':'TEST'}

    if studentid in students:
        return jsonify({studentid:students[studentid]})
    else:
        return not_found()

现在,我试图通过 python requests/pycurl 模块调用这个 url。但是,无论用户名/密码是否有效,它每次都会返回 401 错误。

使用请求:

import requests, base64
usrPass = "admin:secret"
b64Val = base64.b64encode(usrPass)
from requests.auth import HTTPBasicAuth
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
res = requests.get('https://<abc.com>/student/1', auth=HTTPBasicAuth('admin','secret'), headers={'Authorization': 'Basic %s' % b64Val}, data={}, verify=False)
print res

使用 curl :

myCurlPut = pycurl.Curl()
myCurlPut.setopt(pycurl.URL, "https://<abc.com>/student/1")
myCurlPut.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
myCurlPut.setopt(pycurl.USERPWD, "%s:%s" % ('admin', 'secret'))
myCurlPut.setopt(pycurl.SSL_VERIFYPEER, 0)
myCurlPut.setopt(pycurl.HTTPHEADER, ['X-HTTP-Method-Override: GET'])
myCurlPut.perform()

可以,任何人都请帮助我为什么每次都返回 401 错误。请建议。

最佳答案

这是 flask 授权的一个工作示例。

from functools import wraps

from flask import Flask,Response,request, abort


app = Flask(__name__)

def check_auth(name,passw):
    return (name=='admin' and passw=='pass')

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            abort(401)
        return f(*args, **kwargs)
    return decorated


@app.route('/')
@requires_auth
def hello():
    return "Hello World"


if __name__ == "__main__":
    app.run(debug=True)

我的请求文件:

import requests, base64
usrPass = "admin:pass"
b64Val = base64.b64encode(usrPass)
from requests.auth import HTTPBasicAuth
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
res = requests.get('http://127.0.0.1:5000/', auth=HTTPBasicAuth('admin','pass'), headers={'Authorization': 'Basic %s' % b64Val}, data={}, verify=False)
print res

如果你在本地主机上运行它,你应该使用本地主机地址。
什么是 <abc.com>在您的代码中。可能这就是错误。

编辑 2

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired


def gen_token(name,passw, expiration=None):
    s = Serializer(app.config['SECRET_KEY'], expires_in = expiration)
    return s.dumps(name, passw)

def verify_token(token):
    serial = Serializer(app.config['SECRET_KEY'])
    try:
        data = serial.loads(token)
    except BadSignature:
        return "Error"
    except SignatureExpired:
        return "Error"

    name = data[0]
    passw = data[1]

    return name,passw

这些方法可以帮助您开始使用基于 token 的身份验证。

我做的是

  1. 用户通过在 Auth header 中发送带有用户名和密码的请求来从服务器请求 token
  2. 检查 username 后和 password是正确的,您可以使用 gen_token 生成 token 方法。您可以根据您的要求修改此方法。 Read Here
  3. 现在用户发送它从 Auth header 中的方法 2 收到的 token 代替 username . password可以留空或发送None在那个地方。
  4. 收到 token 后,您需要使用 SECRET_KEY 加载它.Exceptions 可以根据您的要求进行处理。如果 token 有效,您将能够获得发送请求的用户,从而执行您的程序。

希望对您有所帮助!

看看这个 link以获得更详细的解释。

关于python - 安全的 Python REST API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37959682/

相关文章:

python - Ctrl+L 不会清除 Python3.3 终端

python - 如果 id 更改,则更改 url 标题 - django

python - 计算Python中两个链接列的频率

rest - 我应该如何将 SAML 登录与 REST API + SPA 应用程序一起使用?

javascript - 如何使用 passport.js 的 passport-local 或其他 Node.js 工具获得完整的 CRUD?

Python 在绘图中使用自定义颜色

java - 在 REST 方法中获取原始请求( springframework )

java - 添加指向 REST 响应的链接

Angular 2 : Get Authorization header

ios - Swift 中的 PFUser logInWithUsernameInBackground - 参数 'target' 调用缺少参数