结合 Flask-restless、Flask-security 和常规 Python 请求

2024-02-06

我的目标是为我的 Web 应用程序提供 REST API。使用:

  • Python 2.7.5
  • 烧瓶==0.10.1
  • Flask-不安==0.13.1
  • Flask-安全==1.7.3

我需要保护对 Web 和 REST 访问的数据的访问。但是,我无法获得任何常规的 pythonrequest尝试连接到安全 API 时成功。

使用本问题末尾提供的全功能模块获得以下输出。

我在使用时设法得到正确答案http://127.0.0.1:5000/api/v1/free_stuff:

>>> import requests
>>> r=requests.get('http://127.0.0.1:5000/api/v1/free_stuff')
>>> print 'status:', r.status_code
status: 200  # all is fine

尝试使用身份验证时http://127.0.0.1:5000/api/v1/protected_stuff:

>>> from requests.auth import HTTPBasicAuth, HTTPDigestAuth
>>> r=requests.get('http://127.0.0.1:5000/api/v1/protected_stuff', 
                   auth=HTTPBasicAuth('test', 'test')) #  the same with ``HTTPDigestAuth``
>>> print 'status:', r.status_code
status: 401
>>> r.json()  # failed!
{u'message': u'401: Unauthorized'}

这是一个用于产生上述结果的虚拟功能模块:

from flask import Flask, render_template, url_for, redirect
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, \
    UserMixin, RoleMixin, login_required, current_user
from flask.ext.restless import APIManager
from flask.ext.restless import ProcessingException

# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'

# Create database connection object
db = SQLAlchemy(app)

# Define Flask-security models
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
#Some additional stuff to query over...
class SomeStuff(db.Model):
    __tablename__ = 'somestuff'
    id = db.Column(db.Integer, primary_key=True)
    data1 = db.Column(db.Integer)
    data2 = db.Column(db.String(10))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    user = db.relationship(User, lazy='joined', join_depth=1, viewonly=True)

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

# API
def auth_func(**kw):
    #import ipdb; ipdb.set_trace()
    if not current_user.is_authenticated():
        raise ProcessingException(description='Not authenticated!',
                code=401)
    return True
apimanager = APIManager(app, flask_sqlalchemy_db=db)

apimanager.create_api(SomeStuff,
    methods=['GET', 'POST', 'DELETE', 'PUT'],
    url_prefix='/api/v1',
    collection_name='free_stuff',
    include_columns=['data1', 'data2', 'user_id'])

apimanager.create_api(SomeStuff,
    methods=['GET', 'POST', 'DELETE', 'PUT'],
    url_prefix='/api/v1',
    preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]),
    collection_name='protected_stuff',
    include_columns=['data1', 'data2', 'user_id'])

# Create a user to test with
@app.before_first_request
def create_user():
    db.create_all()
    user_datastore.create_user(email='test', password='test')
    user_datastore.create_user(email='test2', password='test2')
    ###
    stuff = SomeStuff(data1=2, data2='toto', user_id=1)
    db.session.add(stuff)
    stuff = SomeStuff(data1=5, data2='titi', user_id=1)
    db.session.add(stuff)
    db.session.commit()

# Views
@app.route('/')
@login_required
def home():
    return render_template('index.html')

@app.route('/logout/')
def log_out():
    logout_user()
    return redirect(request.args.get('next') or '/')


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

任何想法?

[编辑] 功能齐全viaWeb 界面,您需要有一个templates子文件夹至少包含以下内容login.html file:

{% block body %}
  <form action="" method=post class="form-horizontal">
    <h2>Signin to FlaskLogin(Todo) Application </h2>
    <div class="control-group">
        <div class="controls">
          <input type="text" id="username" name="username" class="input-xlarge"
            placeholder="Enter Username" required>
        </div>
    </div>

    <div class="control-group">
        <div class="controls">
          <input type="password" id="password" name="password" class="input-xlarge"
            placeholder="Enter Password" required>
        </div>
    </div>

    <div class="control-group">
        <div class="controls">
          <button type="submit" class="btn btn-success">Signin</button>
        </div>
    </div>  
  </form>
{% endblock %}

我终于去了 Flask-JWT (https://pypi.python.org/pypi/Flask-JWT/0.1.0 https://pypi.python.org/pypi/Flask-JWT/0.1.0)

这是我修改后的最小示例:

from flask import Flask, render_template, request, url_for, redirect
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, \
    UserMixin, RoleMixin, login_required, current_user, logout_user
from flask.ext.restless import APIManager
from flask.ext.restless import ProcessingException
from flask.ext.login import user_logged_in
# JWT imports
from datetime import timedelta
from flask_jwt import JWT, jwt_required

# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
# expiration delay for tokens (here is one minute)
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=60)

# Create database connection object
db = SQLAlchemy(app)

# creates the JWT Token authentication  ======================================
jwt = JWT(app)
@jwt.authentication_handler
def authenticate(username, password):
    user = user_datastore.find_user(email=username)
    print '%s vs. %s' % (username, user.email)
    if username == user.email and password == user.password:
        return user
    return None

@jwt.user_handler
def load_user(payload):
    user = user_datastore.find_user(id=payload['user_id'])
    return user

# Define Flask-security models ===============================================
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
#Some additional stuff to query over...
class SomeStuff(db.Model):
    __tablename__ = 'somestuff'
    id = db.Column(db.Integer, primary_key=True)
    data1 = db.Column(db.Integer)
    data2 = db.Column(db.String(10))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    user = db.relationship(User, lazy='joined', join_depth=1, viewonly=True)
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

# Flask-Restless API ==========================================================
@jwt_required()
def auth_func(**kw):
    return True

apimanager = APIManager(app, flask_sqlalchemy_db=db)

apimanager.create_api(SomeStuff,
    methods=['GET', 'POST', 'DELETE', 'PUT'],
    url_prefix='/api/v1',
    collection_name='free_stuff',
    include_columns=['data1', 'data2', 'user_id'])

apimanager.create_api(SomeStuff,
    methods=['GET', 'POST', 'DELETE', 'PUT'],
    url_prefix='/api/v1',
    preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]),
    collection_name='protected_stuff',
    include_columns=['data1', 'data2', 'user_id'])

# Create some users to test with
@app.before_first_request
def create_user():
    db.create_all()
    user_datastore.create_user(email='test', password='test')
    user_datastore.create_user(email='test2', password='test2')
    ###
    stuff = SomeStuff(data1=2, data2='toto', user_id=1)
    db.session.add(stuff)
    stuff = SomeStuff(data1=5, data2='titi', user_id=1)
    db.session.add(stuff)
    db.session.commit()

# Views
@app.route('/')
@login_required
def home():
    print(request.headers)
    return render_template('index.html')

@app.route('/logout/')
def log_out():
    logout_user()
    return redirect(request.args.get('next') or '/')

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

然后,与之互动via requests:

>>>  import requests, json   
>>>  r=requests.get('http://127.0.0.1:5000/api/v1/free_stuff')  # this is OK   
>>>  print 'status:', r.status_code
status: 200   
>>>  r=requests.get('http://127.0.0.1:5000/api/v1/protected_stuff')  # this should fail   
>>>  print 'status:', r.status_code
status: 401   
>>>  print r.json()
{u'status_code': 401, 
u'description': u'Authorization header was missing', 
u'error':    u'Authorization Required'}   
>>>  # Authenticate and retrieve Token   
>>>  r = requests.post('http://127.0.0.1:5000/auth', 
...:                   data=json.dumps({'username': 'test', 'password': 'test'}),
...:                   headers={'content-type': 'application/json'}
...:                   )   
>>>  print 'status:', r.status_code
status: 200   
>>>  token = r.json()['token']   
>>>  # now we have the token, we can navigate to restricted area:   
>>>  r = requests.get('http://127.0.0.1:5000/api/v1/protected_stuff', 
...:                   headers={'Authorization': 'Bearer %s' % token})   
>>>  print 'status:', r.status_code
status: 200 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

结合 Flask-restless、Flask-security 和常规 Python 请求 的相关文章

  • 如何使用 eval dataframe 方法在自定义函数中返回 numpy 数组或列表?

    我正在使用 python 3 X 我正在尝试使用eval https pandas pydata org pandas docs stable generated pandas eval html pandas eval数据框方法 包括这样
  • Matplotlib 颤抖比例

    我正在尝试使用 matplotlib 和 quiver 函数绘制一些箭头 但我想使用数组单独选择每个箭头的长度 http matplotlib sourceforge net api pyplot api html matplotlib p
  • 在 cherokee 和 uwsgi 上部署 Flask [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在尝试部署一个使用 cherokee 和 uwsgi 开发的 Flask Web 应用程序 我安装了 cherokee 和 uwsgi 并正在工作
  • 让 argparse 收集但不响应标志

    我有一个脚本 它接受一些参数 使用其中一些参数来选择要运行的脚本 并将其余参数传递给该脚本 所以它看起来像这样 parser ArgumentParser parser add argument script choices a b par
  • 倒计时:01:05

    如何在 Python 中创建一个看起来像 00 00 分钟和秒 的倒计时时钟 它独立成一行 每次减少一actual秒 则应将旧计时器替换为低一秒的新计时器 01 00变成00 59它实际上击中了00 00 这是我开始使用但想要改造的基本计时
  • 在 Matplotlib 中选择标记大小

    我正在 matplotlib 中用方形标记绘制散点图 如下所示 我想实现这样的目标 这意味着我必须调整标记大小和图形大小 比例 以使标记之间没有空白 每个索引单元还应该有一个标记 x and y都是整数 所以如果y从 60 到 100 应该
  • Python Ctypes:将返回的 C 数组转换为 python 列表,无需 numpy

    我正在使用 Python Ctypes 来访问一些 C 库 我连接到的函数之一返回const double 它实际上是一个双精度数组 当我在Python中得到结果时 如何将该数组转换为Python列表 C函数的签名 const double
  • Python NameError,变量“未定义”

    它返回的错误是 NameError name lives is not defined 我知道代码并不是尽可能高效 这是我的第一个项目 但是无论我尝试做什么 都会弹出这个错误 我尝试为其创建一个全局变量 但这没有帮助 我真的很感激一些帮助
  • TensorFlow 运算符重载

    有什么区别 tf add x y and x y 在 TensorFlow 中 当您使用以下命令构建图表时 您的计算图表会有什么不同 代替tf add 更一般地说 有 或者其他张量超载的操作 如果至少有一个x or y is a tf Te
  • Django + 后台任务如何初始化

    我有一个基本的 django 项目 用作 Condor 计算集群的前端接口来生成模拟 用户可以从 django 应用程序开始模拟 在 Condor 中 与仿真相关的元数据和仿真状态保存在数据库中 我需要添加一个新功能 某些 模拟完成时发出通
  • 如何在 conda 中从一个文件安装多个包而不创建新环境?

    我从当前环境缺少的包的 yml 文件中获取了这些 我如何在当前环境中安装这些 channels defaults dependencies appdirs 1 4 3 py36h28b3542 0 asn1crypto 0 24 0 py3
  • BeautifulSoup - 抓取论坛页面

    我正在尝试抓取论坛讨论并将其导出为 csv 文件 其中包含 线程标题 用户 和 帖子 等行 其中后者是每个人的实际论坛帖子 我是 Python 和 BeautifulSoup 的初学者 所以我对此感到非常困难 我当前的问题是 csv 文件中
  • 检查空查询集

    我想确认这是否是检查空查询集的正确方法 如果这就是为什么我会遇到 UNIQUE 约束错误 syn check Synonym objects filter MD objects get filter dict synonym type St
  • 替换 Python 列表/字典中的值?

    好的 我正在尝试过滤传递给我的列表 字典并稍微 清理 它 因为其中有某些值我需要删除 所以 如果它看起来像这样 records key1 AAA key2 BBB key3 CCC key4 AAA 我如何快速轻松地运行所有内容并将 AAA
  • 如何通过检查传递给 pytest_runtest_teardown 的 Item 对象来确定测试是否通过或失败?

    Pytest 允许您通过实现一个名为的函数来进入每个测试的拆卸阶段pytest runtest teardown在插件中 def pytest runtest teardown item nextitem pass 是否有一个属性或方法it
  • TypeError: 'module' 对象不可调用错误 driver=webdriver("C:\\Python34\\Lib\\site-packages\\selenium\\webdriver\\chromedriver.exe")

    我在 Pycharm 中遇到类似错误 Traceback most recent call last File C PycharmProjects DemoPyth PythonPack1 Prg1 py line 3 in
  • 熊猫:SettingWithCopyWarning:[重复]

    这个问题在这里已经有答案了 我尝试使用以下代码将列转换为 日期 df DATE pd to datetime df DATE or df DATE pd to datetime df DATE 但我收到以下错误 Users xyz anac
  • 在 jupyter 笔记本中运行 pytest 测试函数

    我正在制作有关 python 测试选项的演示 我想要演示的技术之一是 pytest 我计划使用 jupyter ipython 笔记本进行演示 理想情况下 我希望能够在单元格中定义一个测试函数 然后使用 pytest 运行该函数 这样我就可
  • 检查数组中是否有 3 个连续值高于某个阈值

    假设我有一个像这样的 np array a 1 3 4 5 60 43 53 4 46 54 56 78 有没有一种快速方法来获取 3 个连续数字都高于某个阈值的所有位置的索引 也就是说 对于某个阈值th 得到所有x其中 a x gt th
  • 类型错误:“生成器”对象没有属性“__getitem__”

    我编写了一个应该返回字典的生成函数 但是当我尝试打印字段时出现以下错误 print row2 SearchDate TypeError generator object has no attribute getitem 这是我的代码 fro

随机推荐