簡體   English   中英

安全的Python REST API

[英]Secure Python REST APIs

我試圖在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錯誤。 請建議。

這是燒瓶授權的一個工作示例。

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

如果您在localhost上運行此命令,則應使用localhost地址。
您的代碼中的<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

這些方法可以幫助您開始使用基於令牌的身份驗證。

我做的是

  1. 用戶通過在Auth標頭中發送帶有用戶名和密碼的請求來從服務器請求令牌
  2. 檢查usernamepassword是否正確后,可以使用gen_token方法生成令牌。 您可以根據自己的要求修改此方法。 在這里閱讀
  3. 現在,用戶把它發送從方法2中的替代驗證報頭收到該令牌username password可以留空或在那個地方發送None
  4. 當您收到令牌時,您需要使用SECRET_KEY加載它。可以根據您的要求處理異常。 如果令牌有效,您將能夠獲得發送請求的用戶,從而執行您的程序。

希望能幫助到你!

請查看此鏈接以獲取更詳細的說明。

看起來您沒有正確傳遞用戶名和密碼進行身份驗證。 您應該從auth變量獲取的usernamepassword的值。 因此,請嘗試將requires_auth功能更改為:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM