简体   繁体   中英

I am restructuring my Flask-restful app, but having trouble placing the HTTP-auth in order to get app running

Essentially, I have a directory as such:

/app
  runserver.py
  /myapp
    __init__.py
    api.py
    auth.py
    /resources
      __init.py
      users.py
      login.py
    /models
      __init.py
      models.py
    /common
    /assets

In my auth.py I have a standard HTTP-basic username/password authentication. I will use these for areas where login is a must, and I want to verify each user. Login.py is where I need to add my decorator, but the whole app does not run due to this error: AttributeError: 'module' object has no attribute 'login_required'

from flask.ext.httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username, password):
    user = User.query.filter_by(username = username).first()
    if not user or not user.verify_password(password):
        return False
    g.user = user
    return True

@auth.error_handler
def unauthorized():
    return make_response(jsonify({'message': 'Unauthorized'}), 403)

My code for the login.py, which calls the decorator and then asks for the auth.

from flask_restful import Resource, reqparse
from myapp.models.users import User
from myapp import auth 

class login(Resource):
    decorators = [auth.login_required]

    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('userid', type = str , default="")
        self.reqparse.add_argument('username', type = str,  default="")
        self.reqparse.add_argument('password', type = str,  default="")
        super(login, self).__init__()


    def post(self):
        args = self.reqparse.parse_args()
        username = args['username']
        password = args['password']
        message = {'status': 'Authorized'}
    return message

So to wrap it up, my question is: How and where do I add the flask-httpauth class so I can use the decorators. My option right now may be to paste that auth code in every resource class that needs it, but there seems there must be a better way to organize that. Help?

You are importing your auth module when really you want to be importing the HTTPBasicAuth object in that module. It is also possible you're running in to problems due to the fact that your module has the same name as the HTTPBasicAuth object.

I recommend renaming your auth.py to something else, such as authentication.py , and change your import to:

from ..authentication import auth

This gets a bit confusing because you have an auth.py module that defines an auth variable inside.

The line:

from myapp import auth

is importing the module, not the variable defined in it. Change it to:

from myapp.auth import auth

And I think that will work.

Sorry this is a bit old, but for the sake of others with this question, I would suggest not using flask.ext.httpauth. I found it isn't very useful. Here is how I do my HTTP basic auth with flask-restful.

This is in the myapp/ init .py:

from flask import Flask, request
from flask.ext.restful import abort

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth:
            abort(401)
        user = User.query.filter(User.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

Resource script that has a resource that requires authorization to access the resource.

from myapp import requires_auth

@requires_auth
def get(self):
    # do something

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM