Amacım web uygulamasına bir REST API sağlamaktır. Kullanımı:Flask-huzursuz, Flask-güvenlik ve normal Python isteklerini birleştirmek
- Python 2.7.5
- Matara == 0.10.1
- Flask-Huzursuz == 0.13.1
- Flask-Güvenlik == 1.7.3
I Hem web hem de REST erişimi için verilerime erişimi güvenceye almalıyım. Ancak, güvenli API'ye bağlanmaya çalışırken normal python request
başarılı olamıyorum.
Aşağıdaki çıktılar, bu sorunun sonunda sağlanan tam işlevli modül kullanılarak elde edilir. http://127.0.0.1:5000/api/v1/free_stuff
kullanırken
Ben doğru cevabı almak için yönetmek:
>>> 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
ile kimlik doğrulaması çalışırken: Burada
>>> 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'}
yukarıdaki sonuçlar üretmek için kullanılan bir kukla fonksiyonel modüldür:
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()
Herhangi bir fikir?
[değiştir], yaşadığınız en azından aşağıdaki login.html
dosyası templates
alt klasör olması gerekir web arayüzü üzerinden tamamen işlevsel olması için:
{% 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 %}
Bu örneği genişlettik ve bu yaklaşımı kullanarak test ve şablonlama için ipuçları da dahil olmak üzere tam bir örnek proje hazırladım: https://github.com/graup/flask-restless-security Ayrıca tüm paketlerimi tutmaya çalışıyorum güncel. – graup