Flask RESTful API and authenticating for a specifi

2019-09-12 02:13发布

问题:

I am relatively new to RESTful API, so it is certainly possible I am not designing this correctly.

I want to return a different subsets of a JSON user object from /api/users/[user_id] based on who is authenticating. So if the user "alice" is trying to access /api/users/alice, she would get much more of her info (such as private settings, etc) than user "bob" who would simply get her public profile.

I am currently using flask_restful with httpbasicauth. Right now I have the following:

class UserAPI(flask_restful.Resource):
    @g.auth.login_required
    def get(self, username):
        # here is where I want to get the HTTPBasicAuth username
        # to determine how much data to return

        user = User.objects(username=username).exclude('password').first()

        if user is not None:
            return user.to_json()
        else:
            flask_restful.abort(404, message='User not found: ' + username) 

The issue is that I cannot seem to figure out a CLEAN way to get the HTTP basic auth data. I know I could parse the request and decode the base-64 data, but I feel I shouldn't have to do that. Or, even better, find a way to pass the user_id from /api/users/[user_id] into the login_required annotation.

I feel this is would be a very common use case so I can't figure out why I can't find anything in this area. Am I designing this completely wrong?

Thanks very much!

回答1:

I suggest not using flask.ext.httpauth. I didn't find it very useful. I use a decorator that takes the Authorization header and checks it with the db. You can access the username entered in request.authorization.username and the password is in request.authorization.password.

from flask import request
from flask.ext.restful import abort, Resource
from functools import wraps

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth:
            abort(401)
        user = User.objects(username=auth.username).first()
        auth_ok = False
        if user != None:
            auth_ok = verify_password(auth.password) == user.password
        if not auth_ok:
            return abort(401)
        return f(*args, **kwargs)
    return decorated


class UserAPI(Resource):
    @requires_auth
    def get(self):
        user = User.objects(username=request.authorization.username).\
            exclude('password').first()

        if user is not None:
            return user.to_json()
        else:
            abort(404, message='User not found: ' + username)