2013-08-26 42 views
10

Tôi có một ứng dụng bình phục vụ như là phụ trợ REST API. Tôi muốn thực hiện xác thực dựa trên mã thông báo cho chương trình phụ trợ nhưng để thực hiện điều đó, tôi cần truy xuất mã thông báo người dùng. Tài liệu Flask-Security nói rõ ràng rằng để lấy mã thông báo, người dùng cần thực hiện một HTTP POST với các chi tiết xác thực như dữ liệu JSON đến điểm cuối xác thực. Rất tiếc, tôi không hiểu cách lấy mã thông báo CSRF cần thiết để thực hiện yêu cầu đó.Mã thông báo CSRF Flask-Security

Nếu tôi sử dụng trang đăng nhập/mẫu được cung cấp cùng với phần mở rộng, mã thông báo CSRF được chuyển cho khách hàng trong trường ẩn trong biểu mẫu. Câu hỏi là:

làm cách nào để truy xuất mã thông báo CSRF mà không truy cập và phân tích trang đăng nhập, chẳng hạn như từ ứng dụng angularJS sử dụng phương thức $ http hoặc ứng dụng dành cho thiết bị di động?

Rõ ràng là tôi có thể tránh sử dụng Flask-Security và tự triển khai các phần nhưng tôi thiếu kinh nghiệm với các ứng dụng web và tôi cảm thấy tôi có thể đang tiếp cận sai hướng này.

+0

Bạn đã làm điều này như thế nào? – kyrre

+0

Tôi đã tự mình thực hiện lớp bảo mật. Xin lỗi tôi không có câu trả lời tốt hơn cho bạn. – Jacopo

+0

Lưu ý rằng không có cách bảo mật nào để lưu trữ mã thông báo trong angularjs, xem ví dụ: [tại đây] (https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/). Tùy chọn bảo mật là để máy chủ lưu trữ mã thông báo trong cookie chỉ http + bật tính năng bảo vệ CSRF. Nếu tất cả những gì bạn cần nói là angularjs thì bạn cũng có thể sử dụng session (+ anti-CSRF) sau đó. – Adversus

Trả lời

2

Tôi chưa thử nghiệm công trình này, nhưng từ kiểm tra ngắn gọn source code có vẻ như bạn phải gửi yêu cầu GET đến URL đăng nhập với loại nội dung được đặt thành application/json. Flask-Security đáp ứng yêu cầu này với một phiên bản JSON của biểu mẫu đăng nhập và bao gồm mã thông báo. Khi bạn có mã thông báo, bạn có thể gửi yêu cầu POST.

+0

Cảm ơn bạn đã đặt trên con đường bên phải. Trên đầu của việc thực hiện một yêu cầu GET, tôi phải chuyển vào một số dữ liệu json với yêu cầu nếu không 'request.json' rỗng trong Flask và phương thức '_render_json' không được kích hoạt. Thật không may mặc dù điều này gây ra lỗi trên dòng 45 của nguồn bạn đã liên kết vì biểu mẫu không có thuộc tính người dùng. Nhưng một thời gian ngắn nhìn vào mã tôi nghĩ rằng các thuộc tính người dùng nên được thiết lập trong quá trình xác nhận nhưng nó không xảy ra cho yêu cầu này. Tôi sẽ phải tiếp tục đào bới. Cảm ơn một lần nữa – Jacopo

+0

OK Tôi đã tìm ra lỗi. Phương pháp 'validate_on_submit' của Flask-WTF kiểm tra đầu tiên cho 'is_submitted' là sai cho một yêu cầu GET. Điều này ngăn không cho phương thức 'validate' được gọi và thuộc tính 'user' trong biểu mẫu được gán. Tuy nhiên, việc gọi phương thức 'xác thực' bằng cách thủ công sẽ tạo ra lỗi 'mã thông báo CSRF bị thiếu' và chúng tôi sẽ quay lại ngay từ đầu. – Jacopo

4

Tôi đã có một trường hợp sử dụng tương tự và kết thúc giải quyết nó bằng cách làm theo ví dụ này từ các tài liệu Flask-WTF: https://flask-wtf.readthedocs.org/en/latest/csrf.html#ajax

Vì vậy, bằng CSRF Bảo vệ ứng dụng thông qua CsrfProtect(app), các csrf_token() có sẵn trong tất cả các mẫu. Sau đó, bạn có thể dễ dàng cung cấp thẻ thông qua thẻ tập lệnh:

<script type="text/javascript"> 
    var csrftoken = "{{ csrf_token() }}" 
</script> 

Bây giờ, thêm mã thông báo cho dữ liệu bài đăng của bạn cho điểm cuối Flask-Security/login.

+2

Cảm ơn câu trả lời nhưng tôi đã kết thúc triển khai giải pháp quản lý người dùng của riêng mình. Ngoài ra, điều này chỉ hoạt động nếu bạn phục vụ các trang với ứng dụng Flask và bạn hiển thị mẫu với Jinja. Trong trường hợp bạn chỉ sử dụng ứng dụng Flask cho backend (REST API) và giao diện người dùng được phục vụ với các phương thức khác, bạn sẽ phải cung cấp điểm cuối API để truy xuất mã thông báo và hiển thị nó trong phản hồi json. Tôi không chắc làm thế nào điều này sẽ làm việc, tôi sẽ cung cấp cho nó một thử có thể. – Jacopo

0

[Viết như một câu trả lời vì tôi không có đủ uy tín để bình luận]

tôi đã chạy vào vấn đề chính xác giống như Jacopo, trong đó - request.json rỗng và do đó get_auth_token() không được kích hoạt .

BTW - Flask Security documentation nói:

Mã xác thực dựa được kích hoạt bằng cách lấy token của user auth bằng cách thực hiện một HTTP POST với các chi tiết xác thực như dữ liệu JSON so với endpoint xác thực.

Vì vậy, tôi đã cố gắng POST, GET không (Vẫn cùng một vấn đề của request.json trống) tôi gọi/đăng nhập với dữ liệu json như:

{"email": "[email protected]", "password": "test123"} 

và gửi một yêu cầu sử dụng của khách hàng Postman trong Google Chrome .

Tuy nhiên, request.json trống :(

Edit:. Tôi đã có thể di chuyển về phía trước sử dụng mô-đun yêu cầu python Chi tiết here

+0

Xin chào Mandar, tôi hy vọng bạn đã giải quyết vấn đề này, nhưng tôi vừa đăng câu trả lời có thể giúp bạn: http://stackoverflow.com/a/27926284/992509 – SJoshi

+1

câu trả lời bạn đang đưa ra trong blogpost của bạn để bắt đầu (cách triển khai mã thông báo csrf khi sử dụng đăng nhập json trên bình-bảo mật) là bản chất: vô hiệu hóa xác thực csrf trong cấu hình của bình bảo mật. Điều này có tiết kiệm không? Theo [bài viết] này (https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/) miễn là bạn không sử dụng cookie: " CSRF: vì bạn không dựa vào cookie, bạn không cần phải bảo vệ chống lại các yêu cầu trang web chéo ... "Nhưng nó thực sự chỉ là lưu như sử dụng thẻ csrf? – Sebastian

1

tôi đã chiến đấu với vấn đề này trong nhiều giờ đêm qua.Đây là những gì đã kết thúc làm việc cho tôi:

Khi tôi tạo ra ví dụ ứng dụng của tôi:

app = Flask(__name__) 
app.config.from_object(config_by_name[config_name]) 

# Create database connection object 
app.db = db 
app.db.init_app(app) 

CsrfProtect(app) 

Trong HTML/đăng nhập của tôi:

<meta name="csrf-token" content="{{ csrf_token() }}"> 

Từ Postman:

enter image description here

Đây là một giải pháp thay thế mà tôi đã thử và có thể điều này sẽ thành công hơn? Đây là cơ bản trả lời tương tự mà các ứng dụng ví dụ bình-an ninh cho:

enter image description here

2

Vâng, có một cách đơn giản. Visit. Một mục cấu hình WTF_CSRF_ENABLED có thể được đặt thành False để tắt csrf. Sau đó, mọi thứ diễn ra theo ý muốn của bạn.

+1

Điều này đã giải quyết được vấn đề của tôi, cảm ơn. Nó có thể bị downvoted vì nó vô hiệu hóa một tính năng bảo mật. Nhưng nếu máy chủ REST chỉ thực hiện xác thực mã thông báo và không xác thực dựa trên cookie, thì mã thông báo CSRF là không cần thiết. (Tôi hoan nghênh tất cả các ý kiến ​​về điều này!) – velotron

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