2015-06-27 18 views
15

Tôi đang tìm cách bảo mật API Web được tạo bằng Flask và tích hợp với flask-admin để cung cấp giao diện quản trị. Tôi đã tìm kiếm và thấy rằng flask-admin có một bảng quản trị tại /admin và theo mặc định, mọi người đều có thể truy cập vào nó. Nó cung cấp không có hệ thống xác thực và hoàn toàn mở (không có bất kỳ bảo mật nào) vì chúng không giả sử những gì sẽ được sử dụng để cung cấp bảo mật. API này phải được sử dụng trong sản xuất, vì vậy chúng tôi không thể có tuyến đường mở /admin cho mọi người truy cập url. Xác thực đúng là cần thiết.Cách bảo vệ bảng quản trị bình bằng bình bảo mật

Trong views.py Tôi không thể đơn giản đặt tuyến đường /admin và cung cấp xác thực thông qua trang trí vì sẽ ghi đè tuyến đường hiện tại đã được tạo bởi flask-admin để có thể gây ra lỗi.

Nghiên cứu thêm cho thấy có hai mô-đun flask-adminflask-security. Tôi biết rằng flask-admin có phương pháp is_accessible để bảo mật, nhưng nó không cung cấp nhiều chức năng được cung cấp bởi flask-security.

Tôi không tìm thấy bất kỳ phương pháp nào để đảm bảo điểm kết thúc /admin cộng với tất cả các điểm kết thúc khác bắt đầu bằng /admin chẳng hạn như /admin/<something>.

Tôi đang tìm cách cụ thể để thực hiện tác vụ này với bảo mật bình. Nếu không thể, vui lòng đề xuất các lựa chọn thay thế.

PS: Tôi biết tôi có thể tự khóa ngnix, nhưng đó sẽ là tùy chọn cuối cùng. Nếu tôi có thể có hệ thống xác thực thông qua flask-security, điều đó sẽ tốt.

+1

Cơ chế xác thực của Flask-Security (thông qua Flask-Login) kiểm soát giá trị trả về của 'current_user.is_authenticated()'. Việc trả về điều này (có thể kết hợp với một số kiểu kiểm tra vai trò/quyền) trong triển khai 'is_accessible' của bạn sẽ cho bạn khả năng sử dụng tính năng bảo vệ Flask-Security trong Flask-Admin. – jonafato

Trả lời

4

Bạn nên kiểm tra các dự án Flask-Security-Admin, tôi nghĩ rằng nó bao gồm khá rõ ràng những gì bạn đang tìm kiếm.

Taken trực tiếp từ các liên kết ở trên:

  • Khi bạn lần đầu tiên ghé thăm trang chủ của ứng dụng, bạn sẽ được nhắc nhở để đăng nhập, nhờ Flask-Security.
  • Nếu bạn đăng nhập bằng [email protected] và mật khẩu = mật khẩu, bạn sẽ có vai trò "người dùng cuối".
  • Nếu bạn đăng nhập bằng [email protected] và mật khẩu = mật khẩu, bạn sẽ có vai trò "quản trị".
  • Hoặc vai trò được phép truy cập trang chủ.
  • Hoặc vai trò được phép truy cập trang/quản trị viên. Tuy nhiên, trừ khi bạn có vai trò "quản trị", bạn sẽ không thấy các tab quản trị người dùng và vai trò trên trang này.
  • Chỉ vai trò quản trị mới được phép truy cập vào các trang phụ của/trang quản trị như/admin/userview. Nếu không, bạn sẽ nhận được phản hồi "bị cấm".
  • Lưu ý rằng, khi chỉnh sửa người dùng, tên của các vai trò sẽ tự động được điền thông qua Flask-Admin.
  • Bạn có thể thêm và chỉnh sửa người dùng cũng như vai trò. Người dùng kết quả sẽ có thể đăng nhập (trừ khi bạn đặt active = false) và, nếu họ có vai trò "quản trị", sẽ có thể thực hiện quản trị.

Mã liên quan nằm ở main.py, và được nhận xét rõ ràng để giải thích làm thế nào để tái tạo quá trình đảm bảo bảng bình-admin sử dụng bình-an ninh.

Các cơ bản nhất, mảnh phù hợp với bạn là như sau (dòng 152-):

# Prevent administration of Users unless the currently logged-in user has the "admin" role 
def is_accessible(self): 
    return current_user.has_role('admin') 

Tôi hy vọng điều này là hữu ích.

+1

Cảm ơn bạn! Sau một số nghiên cứu và đào sâu hơn, tôi đã làm cho nó hoạt động. –

+0

Cảm ơn bạn đã cung cấp điều này. Tôi đã tìm kiếm câu trả lời trong một giờ và cuối cùng tìm thấy nó với bạn ở đây. – applecrusher

1

Có phần về an ninh trong tài liệu Flask-Admin: http://flask-admin.readthedocs.io/en/latest/introduction/#authorization-permissions

+0

Tôi đã xem xét nó trước khi đăng bài ở đây và trong phần này các ví dụ cho thấy về việc sử dụng 'flask-admin' và không phải là 'flask-security'. Tôi đặc biệt tìm cách làm điều đó thông qua 'bình an ninh' vì nó cung cấp nhiều chức năng hơn mà 'bình-đăng nhập'. Bất kỳ trợ giúp sẽ được đánh giá cao. –

+0

@Joes https://stackoverflow.com/questions/46914054/access-control-for-flask-admin – Sparrowcide

6

Vì đây là kết quả đầu tiên cho tìm kiếm google "quản trị an toàn bình an toàn" và chưa có giải pháp ngoài hộp, tôi nghĩ tôi có thể đóng góp.

Một câu hỏi tương tự được hỏi về dự án bình-quản trị Issue List và một ví dụ đơn giản sử dụng bình-đăng nhập và mogodb được cung cấp here.

Tôi đã tạo ví dụ bằng cách sử dụng SQLAchemy cho cơ sở dữ liệu sqlite và bảo mật bình. Xem ứng dụng mẫu bình dưới đây:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import os 
import os.path as op 
from flask import Flask, render_template, url_for, request 
from flask_sqlalchemy import SQLAlchemy 
from sqlalchemy.event import listens_for 
from flask.ext.security import current_user, login_required, RoleMixin, Security, SQLAlchemyUserDatastore, UserMixin 
from flask_admin import Admin, AdminIndexView 
from flask_admin.contrib import sqla 

# Create application 
app = Flask(__name__) 

# Create dummy secrety key so we can use sessions 
app.config['SECRET_KEY'] = '123456790' 

# Create in-memory database 
app.config['DATABASE_FILE'] = 'sample_db.sqlite' 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE'] 
app.config['SQLALCHEMY_ECHO'] = True 
db = SQLAlchemy(app) 

# Create directory for file fields to use 
file_path = op.join(op.dirname(__file__), 'static/files') 

# 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')) 

# Create Security 
user_datastore = SQLAlchemyUserDatastore(db, User, Role) 
security = Security(app, user_datastore) 

# Only needed on first execution to create first user 
#@app.before_first_request 
#def create_user(): 
# db.create_all() 
# user_datastore.create_user(email='[email protected]', password='pass') 
# db.session.commit() 

class AnyModel(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.Unicode(64)) 

    def __unicode__(self): 
     return self.name 

class MyAdminIndexView(AdminIndexView): 
    def is_accessible(self): 
     return current_user.is_authenticated() # This does the trick rendering the view only if the user is authenticated 

# Create admin. In this block you pass your custom admin index view to your admin area 
admin = Admin(app, 'Admin Area', template_mode='bootstrap3', index_view=MyAdminIndexView()) 


# Add views 
admin.add_view(sqla.ModelView(AnyModel, db.session)) 

# To acess the logout just type the route /logout on browser. That redirects you to the index 
@login_required 
@app.route('/login') 
def login(): 
    return redirect('/admin') 

@app.route('/') 
def index(): 
    return render_template('index.html') 


if __name__ == '__main__': 

    # Build sample db on the fly, if one does not exist yet. 
    db.create_all() 
    app.run(debug=True) 

Vui lòng tham khảo các tài liệu bình-an ninh cho học how to customize the login page.

Hy vọng điều này sẽ hữu ích.

0

Tôi sử dụng câu trả lời @ RamiMac cho tất cả các chế độ xem phụ, nhưng đối với chỉ mục một (theo mặc định /admin), tôi sử dụng phương pháp này, đóng lại phương thức với vai trò admin cần xem.

@app.before_first_request 
def restrict_admin_url(): 
    endpoint = 'admin.index' 
    url = url_for(endpoint) 
    admin_index = app.view_functions.pop(endpoint) 

    @app.route(url, endpoint=endpoint) 
    @roles_required('admin') 
    def secure_admin_index(): 
     return admin_index() 

Trong dự án của tôi, điều này đi trực tiếp sau khi tất cả các mã Flask-Admin của tôi, mà là chính nó trong kịch bản khởi động riêng của mình, custom_flaskadmin.py.

Các vấn đề liên quan