Mein Ziel ist es, eine REST-API für meine Webanwendung bereitzustellen. Mit:Kombinieren Flask-unruhig, Flask-Sicherheit und regelmäßige Python-Anfragen
- Python 2.7.5
- Flask == 0.10.1
- Flask-Restless == 0.13.1
- Flask-Sicherheit == 1.7.3
I müssen den Zugriff auf meine Daten sowohl für den Web- als auch für den REST-Zugriff sicherstellen. Ich bin jedoch nicht in der Lage, einen regulären Python request
erfolgreich auszuführen, wenn ich versuche, eine Verbindung mit der gesicherten API herzustellen.
Die folgenden Ausgaben werden mit dem voll funktionsfähigen Modul erhalten, das am Ende dieser Frage bereitgestellt wird.
schaffe ich eine richtige Antwort zu erhalten, wenn http://127.0.0.1:5000/api/v1/free_stuff
mit:
>>> 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
Beim Versuch, die Authentifizierung mit 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'}
hier ein Dummy-Funktionsmodul die obigen Ergebnisse verwendet wird, produzieren:
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()
Irgendeine Idee?
[Bearbeiten] sein, voll funktionsfähige über Web-Interface, können Sie einen templates
Unterordner mit mindestens die folgenden login.html
Datei haben müssen:
{% 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 %}
Ich erweiterte dieses Beispiel und machte ein komplettes Beispielprojekt mit diesem Ansatz einschließlich Stubs zum Testen und Templating: https://github.com/graup/flask-restless-security Ich versuche auch, alle Pakete zu behalten auf dem Laufenden. – graup