8

मेरा लक्ष्य अपने वेब आवेदन करने के लिए एक REST API प्रदान करना है। का उपयोग करना:का मेल कुप्पी के बेचैन, बोतल-सुरक्षा और नियमित रूप से अजगर का अनुरोध करता है

  • अजगर 2.7.5
  • बोतल == 0.10.1
  • कुप्पी के बेचैन == 0.13.1
  • कुप्पी के सुरक्षा == 1.7.3

मैं वेब और आरईएसटी एक्सेस दोनों के लिए मेरे डेटा तक पहुंच सुरक्षित करने की आवश्यकता है। हालांकि, मैं सुरक्षित एपीआई से कनेक्ट करने का प्रयास करते समय कोई नियमित पायथन request सफल होने में असमर्थ हूं।

निम्नलिखित आउटपुट इस सवाल के अंत में ठीक प्रकार से कार्य मॉड्यूल का उपयोग कर प्राप्त कर रहे हैं।

मैं जब 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() 

किसी भी विचार?

पूरी तरह से कार्य के माध्यम से वेब इंटरफेस है, आप एक templates उप-फ़ोल्डर होने कम से कम निम्नलिखित login.html फ़ाइल की आवश्यकता होने के लिए [संपादित करें]: (

{% 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 %} 

उत्तर

15

मैं अंत में कुप्पी के जेडब्ल्यूटी के पास गया 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() 

फिर, यह के साथ बातचीत करने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 
+3

मैंने इस उदाहरण को विस्तारित किया और परीक्षण और टेम्पलेटिंग के लिए स्टब्स समेत इस दृष्टिकोण का उपयोग करके एक पूर्ण नमूना प्रोजेक्ट बनाया: https://github.com/graup/flask-restless-security मैं सभी पैकेजों को रखने की भी कोशिश करता हूं आधुनिक। – graup

1

आपका (अजगर अनुरोध मॉड्यूल का उपयोग करने का) मूल प्रश्न मुझे unstuck पाने :) मैं कुछ भी अलग नहीं किया मदद की।

मैं कुप्पी के बेचैन (अभी तक)

FWIW उपयोग नहीं कर रहा है - मैं का उपयोग कर प्रमाणीकरण टोकन प्राप्त करने में सक्षम था, "बस" कुप्पी के सुरक्षा (यानी कुप्पी के जेडब्ल्यूटी का उपयोग किए बिना)

देखें विवरण के लिए here

+0

सीएसआरएफ टोकन को बंद करने के लिए अच्छा कॉल! भारी दर्द!:) जो मैं बता सकता हूं, जेडब्ल्यूटी का उपयोग करना एक विकल्प हो सकता है (ऊपर दिए गए उत्तर में उल्लिखित), लेकिन सर्वर-साइड ऑथटोकेंस संग्रहीत करना अमान्य उद्देश्यों के लिए बहुत आसान है। – SJoshi

+0

इसके अलावा, मैं फ्लास्क-सुरक्षा के साथ भी पोस्टमैन को चलाने के साथ लड़ रहा हूं। बस यह उम्मीद के रूप में काम कर रहा है (sorta)। मैंने अपनी सामग्री-प्रकार को एप्लिकेशन/जेसन पर सेट किया है, मेरा एंडपॉइंट/लॉगिन करें, और फिर मैं जेएसओएन के 'कच्चे' डेटा में प्रवेश करता हूं, और फिर मैं अपना कच्चा डेटा JSON (ईमेल/पासवर्ड) के रूप में दर्ज करता हूं। यह काम करता है, मुझे एक बार JSON टोकन वापस देता है, लेकिन वहां से, जब मैं लॉग इन हूं, तो यह मेरे index.html पृष्ठ को वापस थूक देगा। फिर से टोकन प्राप्त करने के लिए, मुझे/लॉगआउट और/फिर से लॉगिन करने की आवश्यकता है ... किंडा लंगड़ा। मुझे लगता है कि यह किसी भी तरह कुकीज़ भेजना होगा, लेकिन POSTman उन लोगों का उपयोग नहीं करना चाहिए था। – SJoshi

+0

फ्लास्क-सुरक्षा एक ऑथ टोकन तंत्र से अधिक प्रदान करता है (जो फ्लास्क-जेडब्ल्यूटी प्रदान करता है)। तो यह कई अन्य चीजों के लिए एक विकल्प हो सकता है https://pythonhosted.org/Flask-Security/। क्या आप मुझे सही यूआरएल पर इंगित कर सकते हैं जहां मैं auth_token के लिए समाप्ति_टाइम सेट कर सकता हूं? रास्ते में अपने ब्लॉगपोस्ट के लिए धन्यवाद – Hussain

संबंधित मुद्दे