简体   繁体   English

flask_restful没有使用于flask.ext.login的login_required装饰器

[英]flask_restful not working with flask.ext.login's login_required decorator

So I'm writing a very basic restful API in flask and the @login_required decorator throws the 'as_view' error. 所以我正在写一个非常基本的restful API,而@login_required装饰器会抛出'as_view'错误。 I know it's the decorator because if i comment it out the app runs just fine. 我知道这是装饰者,因为如果我评论它应用程序运行得很好。 Any thoughts/solutions. 任何想法/解决方案。 I've tried inheriting UserMixin and Resource inside the User class. 我尝试在User类中继承UserMixin和Resource。 I read somewhere it has to do with Resource as_view being inherited. 我读到了与继承的资源as_view有关的地方。 If it matters I use flask-script to run the app. 如果重要,我使用flask-script来运行应用程序。 Thanks guys/girls. 谢谢你们。 Code Below, traceback under code 代码下面,代码下的回溯

import json

from flask import Flask, request
from flask_restful import Resource, abort, Api, reqparse
from flask.views import MethodView
from flask.ext.login import LoginManager, UserMixin, login_required, login_user, logout_user, current_user
from lib.mongo import db

from bson.objectid import ObjectId

from crontab import CronTab


app = Flask(__name__)
app.config["SECRET_KEY"] = ''
login_manager = LoginManager()
login_manager.init_app(app)
api = Api(app)

##############################################
##############################################
#######USER CLASS FOR LOGGING IN AND OUT
##############################################
##############################################
class User(UserMixin):
  def __init__(self, username, api_key, id, active=True):
    self.username = username
    self.api_key = api_key
    self.id = id
    self.active = active

  def is_active(self):
    account = db.users.find_one({ 'username': self.username, 'api_key': self.api_key})
    if account is not None:
      if not account['username'] == self.username and account['api_key'] == self.api_key:
        self.active = False
    else:
      self.active = False
    return self.active

  def is_anonymous(self):
    return False

  def is_authenticated(self):
    return True

  def get_id(self):
    return str(db.accounts.find_one({ 'username': self.username, 'api_key': self.api_key})['_id'])


@login_manager.user_loader
def load_user(userid):
  user_rec = db.accounts.find_one({'_id': ObjectId(userid)})
  user = User(user_rec['username'], user_rec['api_key'], user_rec['_id'])
  return user


class Auth(Resource):
  def get(self):
    api_key = request.args.get('api_key', '')
    username = request.args.get('username', '')
    if username == '':
      abort(400, message='username was not provided')
    if api_key == '':
      abort(400, message='api key was not provided')

    account = db.accounts.find_one({'username': username, 'api_key': api_key})
    if account:
      if account['account_type'] == 'admin':
        user = User(username, api_key, account['_id'])
        login_user(user)
        return {'auth': 'successful', 'status_code': 200}, 200
      else:
        abort(401, message='you are not an admin')
    else:
       abort(401, message='could not auth account')


@login_required
class ListCronJobs(Resource):
  def get(self):
    cron = CronTab(user=True)
    cronjobs = []
    for line in cron.lines:
      cronjobs.append(line)
    return {'data': cronjobs}


api.add_resource(Auth, '/api/auth')
api.add_resource(ListCronJobs, '/api/listcronjobs')

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

Traceback: 追溯:

File "manage.py", line 2, in <module>
    from app import app
  File "/Users/user/folder/app/__init__.py", line 90, in <module>
    api.add_resource(ListCronJobs, '/ListCronJobs/listcronjobs')
  File "/Users/user/folder/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 401, in add_resource
    self._register_view(self.app, resource, *urls, **kwargs)
  File "/Users/user/folder/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 441, in _register_view
    resource_func = self.output(resource.as_view(endpoint, *resource_class_args,
AttributeError: 'function' object has no attribute 'as_view'

EDIT: So I fixed the issue by placing @login_required above the get(self) instead of decorating the class 编辑:所以我通过将@login_required置于get(self)之上而不是装饰类来解决问题

class ListCronJobs(Resource):
  @login_required
  def get(self):
    cron = CronTab(user=True)
    cronjobs = []
    for line in cron.lines:
      cronjobs.append(line)
    return {'data': cronjobs}

The new issue is that when I make that request (curl " http://127.0.0.1:5000/api/listcronjobs " ) I get the error: "message": "The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (eg a bad password), or your browser doesn't understand how to supply the credentials required." 新问题是,当我提出请求时(卷曲“ http://127.0.0.1:5000/api/listcronjobs ”)我收到错误:“message”:“服务器无法验证您是否有权访问请求的URL。您提供了错误的凭据(例如密码错误),或者您的浏览器不了解如何提供所需的凭据。“

I make the request after I auth in with curl 我在用curl认证后提出请求

So this the working version. 所以这是工作版。

from flask import Flask, request
from flask_restful import Resource, abort, Api
from flask.ext.login import LoginManager, UserMixin, login_required, login_user#, logout_user, current_user
from lib.mongo import db

from bson.objectid import ObjectId

from crontab import CronTab


app = Flask(__name__)
app.config["SECRET_KEY"] = 'm\\x88\xe2@\xb18\\x82\xa9\x7f\\x84l[G\x8d\xe6N\x8fJl\\x95{\xd2F\\x10'
login_manager = LoginManager()
login_manager.init_app(app)
api = Api(app)

##############################################
##############################################
#######USER CLASS FOR LOGGING IN AND OUT
##############################################
##############################################
class User(UserMixin):
  def __init__(self, username, api_key, id, active=True):
    self.username = username
    self.api_key = api_key
    self.id = id
    self.active = active

  def is_active(self):
    account = db.users.find_one({ 'username': self.username, 'api_key': self.api_key})
    if account is not None:
      if not account['username'] == self.username and account['api_key'] == self.api_key:
        self.active = False
    else:
      self.active = False
    return self.active

  def is_anonymous(self):
    return False

  def is_authenticated(self):
    return True

  def get_id(self):
    return str(db.accounts.find_one({ 'username': self.username, 'api_key': self.api_key})['_id'])


@login_manager.user_loader
def load_user(userid):
  user_rec = db.accounts.find_one({'_id': ObjectId(userid)})
  user = User(user_rec['username'], user_rec['api_key'], user_rec['_id'])
  return user


class Auth(Resource):
  def get(self):
    api_key = request.args.get('api_key', '')
    username = request.args.get('username', '')
    if username == '':
      abort(400, message='username was not provided')
    if api_key == '':
      abort(400, message='api key was not provided')

    account = db.accounts.find_one({'username': username, 'api_key': api_key})
    if account:
      if account['account_type'] == 'admin':
        user = User(username, api_key, account['_id'])
        login_user(user)
        return {'auth': 'successful', 'status_code': 200}, 200
      else:
        abort(401, message='you are not an admin')
    else:
       abort(401, message='could not auth account')



class ListCronJobs(Resource):
  @login_required
  def get(self):
    cron = CronTab(user=True)
    cronjobs = []
    for line in cron.lines:
      cronjobs.append(line)
    return {'data': cronjobs}

api.add_resource(Auth, '/api/auth')
api.add_resource(ListCronJobs, '/api/listcronjobs')

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

Instead of running the test with curl I ran them with python's requests module and created a session. 我没有使用curl运行测试,而是使用python的请求模块运行它们并创建了一个会话。

import requests
s = requests.Session()
res = s.get('http://127.0.0.1:5000/api/auth?username=foo&api_key=bar')
print res.json()
res = s.get('http://127.0.0.1:5000/api/listcronjobs')
print res.json()

When using curl to auth in the session wasn't kept, so the API call to list the cronjobs was rejected. 在会话中使用curl进行身份验证时没有保留,因此拒绝列出cronjobs的API调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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