Thứ hai, 06/07/2020 | 00:00 GMT+7

Cách thêm xác thực vào ứng dụng của bạn bằng Flask-Login

Cho phép user đăng nhập vào ứng dụng của bạn là một trong những tính năng phổ biến nhất mà bạn sẽ thêm vào ứng dụng web của bạn . Bài viết này sẽ trình bày cách thêm xác thực vào ứng dụng Flask của bạn với gói Flask-Login .

Ảnh động gif của ứng dụng Flask và hộp đăng nhập

Ta sẽ xây dựng một số trang đăng ký và đăng nhập cho phép user đăng nhập và truy cập các trang được bảo vệ mà user chưa đăng nhập không thể nhìn thấy. Ta sẽ lấy thông tin từ mô hình user và hiển thị thông tin đó trên các trang được bảo vệ của ta khi user đăng nhập để mô phỏng profile trông như thế nào.

Ta sẽ đề cập đến những điều sau trong bài viết này:

  • Sử dụng thư viện Flask-Login để quản lý phiên
  • Sử dụng trình Flask tích hợp sẵn để băm password
  • Thêm các trang được bảo vệ vào ứng dụng của ta chỉ dành cho user đã đăng nhập
  • Sử dụng Flask-SQLAlchemy để tạo mô hình user
  • Tạo biểu mẫu đăng ký và đăng nhập cho user của ta để tạo account và đăng nhập
  • Thông báo lỗi flash lại cho user khi có sự cố
  • Sử dụng thông tin từ account của user để hiển thị trên trang profile

Mã nguồn của dự án này có sẵn trên GitHub .

Yêu cầu

Để hoàn thành hướng dẫn này, bạn cần những thứ sau:

Ứng dụng của ta sẽ sử dụng mô hình nhà máy ứng dụng Flask với các bản thiết kế. Ta sẽ có một bản thiết kế xử lý mọi thứ liên quan đến xác thực và ta sẽ có một bản thiết kế khác cho các tuyến đường thông thường của ta , bao gồm index và trang profile được bảo vệ. Trong một ứng dụng thực, bạn có thể chia nhỏ chức năng theo bất kỳ cách nào bạn thích, nhưng giải pháp được đề cập ở đây sẽ hoạt động tốt cho hướng dẫn này.

Dưới đây là một sơ đồ để cung cấp cảm giác về cấu trúc file dự án của bạn sẽ trông như thế nào sau khi bạn hoàn thành hướng dẫn:

. └── flask_auth_app     └── project         ├── __init__.py       # setup our app         ├── auth.py           # the auth routes for our app         ├── db.sqlite         # our database         ├── main.py           # the non-auth routes for our app         ├── models.py         # our user model         └── templates             ├── base.html     # contains common layout and links             ├── index.html    # show the home page             ├── login.html    # show the login form             ├── profile.html  # show the profile page             └── signup.html   # show the signup form 

Khi ta hoàn thành hướng dẫn, ta sẽ tạo các folder và file này.

Bước 1 - Cài đặt gói

Có ba gói chính mà ta cần cho dự án của bạn :

  • Bình giữ nhiệt
  • Flask-Login: để xử lý các phiên user sau khi xác thực
  • Flask-SQLAlchemy: đại diện cho mô hình user và giao diện với database của ta

Ta sẽ sử dụng SQLite để tránh phải cài đặt thêm bất kỳ phần phụ thuộc nào cho database .

Đầu tiên, ta sẽ bắt đầu với việc tạo folder dự án:

  • mkdir flask_auth_app

Tiếp theo, ta cần chuyển đến folder dự án:

  • cd flask_auth_app

Bạn cần tạo một môi trường Python nếu bạn không có. Tùy thuộc vào cách Python được cài đặt trên máy của bạn, các lệnh của bạn sẽ trông tương tự như:

  • python3 -m venv auth
  • source auth/bin/activate

Lưu ý: Bạn có thể tham khảo hướng dẫn có liên quan đến môi trường local của bạn để cài đặt venv .

Chạy các lệnh sau từ môi trường ảo của bạn để cài đặt các gói cần thiết:

  • pip install flask flask-sqlalchemy flask-login

Đến đây bạn đã cài đặt các gói, bạn đã sẵn sàng để tạo file ứng dụng chính.

Bước 2 - Tạo file ứng dụng chính

Hãy bắt đầu bằng cách tạo một folder project :

  • mkdir project

Tệp đầu tiên ta sẽ làm việc trên sẽ là file __init__.py cho dự án của ta :

  • nano project/__init__.py

Tệp này sẽ có chức năng tạo ứng dụng của ta , sẽ khởi tạo database và đăng ký các bản thiết kế của ta . Hiện tại, điều này sẽ không hiệu quả nhiều nhưng nó cần thiết cho phần còn lại của ứng dụng của ta . Ta cần khởi tạo SQLAlchemy, đặt một số giá trị cấu hình và đăng ký các bản thiết kế của ta tại đây.

project / __ init__.py
from flask import Flask from flask_sqlalchemy import SQLAlchemy  # init SQLAlchemy so we can use it later in our models db = SQLAlchemy()  def create_app():     app = Flask(__name__)      app.config['SECRET_KEY'] = 'secret-key-goes-here'     app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'      db.init_app(app)      # blueprint for auth routes in our app     from .auth import auth as auth_blueprint     app.register_blueprint(auth_blueprint)      # blueprint for non-auth parts of app     from .main import main as main_blueprint     app.register_blueprint(main_blueprint)      return app 

Bây giờ ta đã có file ứng dụng chính, ta có thể bắt đầu thêm vào các tuyến đường của bạn .

Bước 3 - Thêm tuyến đường

Đối với các tuyến đường của ta , ta sẽ sử dụng hai bản thiết kế. Đối với kế hoạch chi tiết chính của ta , ta sẽ có trang chủ ( / ) và trang profile ( /profile ) sau khi ta đăng nhập. Nếu user cố gắng truy cập trang profile mà không đăng nhập, họ sẽ được đưa đến thông tin đăng nhập lộ trình.

Đối với bản thiết kế xác thực của ta , ta sẽ có các tuyến để truy xuất cả trang đăng nhập ( /login ) và trang đăng ký ( /sign-up ). Ta cũng sẽ có các tuyến để xử lý các yêu cầu POST từ cả hai tuyến đó. Cuối cùng, ta sẽ có một lộ trình đăng xuất ( /logout ) để đăng xuất một user đang hoạt động.

Hiện tại, ta sẽ xác định login , signuplogout với các lợi nhuận đơn giản. Ta sẽ truy cập lại chúng ở bước sau và cập nhật chúng với chức năng mong muốn.

Đầu tiên, tạo main.py cho main_blueprint của bạn:

  • nano project/main.py
project / main.py
from flask import Blueprint from . import db  main = Blueprint('main', __name__)  @main.route('/') def index():     return 'Index'  @main.route('/profile') def profile():     return 'Profile' 

Tiếp theo, tạo auth.py cho auth_blueprint của bạn:

  • nano project/auth.py
project / auth.py
from flask import Blueprint from . import db  auth = Blueprint('auth', __name__)  @auth.route('/login') def login():     return 'Login'  @auth.route('/signup') def signup():     return 'Signup'  @auth.route('/logout') def logout():     return 'Logout' 

Trong một terminal , bạn có thể cài đặt các FLASK_APPFLASK_DEBUG giá trị:

  • export FLASK_APP=project
  • export FLASK_DEBUG=1

FLASK_APP môi trường FLASK_APP hướng dẫn Flask cách tải ứng dụng. Nó sẽ trỏ đến nơi create_app được đặt. Đối với nhu cầu của ta , ta sẽ chỉ đến folder project .

FLASK_DEBUG môi trường FLASK_DEBUG được bật bằng cách đặt nó thành 1 . Điều này sẽ kích hoạt một trình gỡ lỗi sẽ hiển thị các lỗi ứng dụng trong trình duyệt.

Đảm bảo rằng bạn đang ở trong folder flask_auth_app và sau đó chạy dự án:

  • flask run

Bây giờ, trong một trình duyệt web, bạn có thể chuyển đến năm URL càng tốt và xem văn bản trở lại đã được quy định tại auth.pymain.py .

Ví dụ, truy cập localhost:5000/profile hiển thị: Profile :

Ảnh chụp màn hình của dự án tại cổng localhost 5000 trong trình duyệt

Bây giờ ta đã xác minh các tuyến đường của ta đang hoạt động như mong đợi, ta có thể chuyển sang tạo mẫu.

Bước 4 - Tạo mẫu

Hãy tiếp tục và tạo các mẫu được sử dụng trong ứng dụng của ta . Đây là bước đầu tiên trước khi ta có thể triển khai chức năng đăng nhập thực tế. Ứng dụng của ta sẽ sử dụng bốn mẫu:

  • index.html
  • profile.html
  • login.html
  • signup.html

Ta cũng sẽ có một mẫu cơ sở sẽ có mã chung cho mỗi trang. Trong trường hợp này, mẫu cơ sở sẽ có các liên kết chuyển và bố cục chung của trang. Hãy tạo chúng ngay bây giờ.

Đầu tiên, tạo một folder templates folder project :

  • mkdir -p project/templates

Sau đó, tạo base.html :

  • nano project/templates/base.html

Tiếp theo, thêm mã sau vào file base.html :

project / Template / base.html
<!DOCTYPE html> <html>  <head>     <meta charset="utf-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1">     <title>Flask Auth Example</title>     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" /> </head>  <body>     <section class="hero is-primary is-fullheight">          <div class="hero-head">             <nav class="navbar">                 <div class="container">                      <div id="navbarMenuHeroA" class="navbar-menu">                         <div class="navbar-end">                             <a href="{{ url_for('main.index') }}" class="navbar-item">                                 Home                             </a>                             <a href="{{ url_for('main.profile') }}" class="navbar-item">                                 Profile                             </a>                             <a href="{{ url_for('auth.login') }}" class="navbar-item">                                 Login                             </a>                             <a href="{{ url_for('auth.signup') }}" class="navbar-item">                                 Sign Up                             </a>                             <a href="{{ url_for('auth.logout') }}" class="navbar-item">                                 Logout                             </a>                         </div>                     </div>                 </div>             </nav>         </div>          <div class="hero-body">             <div class="container has-text-centered">                {% block content %}                {% endblock %}             </div>         </div>     </section> </body>  </html> 

Mã này sẽ tạo ra một loạt các liên kết menu đến từng trang của ứng dụng và một khu vực nơi nội dung sẽ xuất hiện.

Lưu ý: Phía sau, ta đang sử dụng Bulma để xử lý kiểu dáng và bố cục. Để tìm hiểu sâu hơn về Bulma, hãy xem xét đọc tài liệu chính thức của Bulma .

Tiếp theo, tạo các templates/index.html :

  • nano project/templates/index.html

Thêm mã sau vào file mới tạo để thêm nội dung vào trang:

project / Template / index.html
{% extends "base.html" %}  {% block content %} <h1 class="title">   Flask Login Example </h1> <h2 class="subtitle">   Easy authentication and authorization in Flask. </h2> {% endblock %} 

Mã này sẽ tạo một trang index cơ bản với tiêu đề và phụ đề.

Tiếp theo, tạo các templates/login.html :

  • nano project/templates/login.html

Mã này tạo một trang đăng nhập với các trường cho EmailMật khẩu . Ngoài ra còn có một hộp kiểm để "ghi nhớ" một phiên đã đăng nhập.

project / Template / login.html
{% extends "base.html" %}  {% block content %} <div class="column is-4 is-offset-4">     <h3 class="title">Login</h3>     <div class="box">         <form method="POST" action="/login">             <div class="field">                 <div class="control">                     <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="password" name="password" placeholder="Your Password">                 </div>             </div>             <div class="field">                 <label class="checkbox">                     <input type="checkbox">                     Remember me                 </label>             </div>             <button class="button is-block is-info is-large is-fullwidth">Login</button>         </form>     </div> </div> {% endblock %} 

Tiếp theo, tạo các templates/signup.html :

  • nano project/templates/signup.html

Thêm mã sau để tạo trang đăng ký với các trường email, tên và password :

project / Template / signup.html
{% extends "base.html" %}  {% block content %} <div class="column is-4 is-offset-4">     <h3 class="title">Sign Up</h3>     <div class="box">         <form method="POST" action="/signup">             <div class="field">                 <div class="control">                     <input class="input is-large" type="email" name="email" placeholder="Email" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="text" name="name" placeholder="Name" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="password" name="password" placeholder="Password">                 </div>             </div>              <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>         </form>     </div> </div> {% endblock %} 

Tiếp theo, tạo các templates/profile.html :

  • nano project/templates/profile.html

Thêm mã này để tạo một trang đơn giản với tiêu đề được mã hóa cứng để chào đón Anthony :

project / Template / profile.html
{% extends "base.html" %}  {% block content %} <h1 class="title">   Welcome, Anthony! </h1> {% endblock %} 

Sau đó, ta sẽ thêm mã để chào hỏi động mọi user .

Sau khi bạn đã thêm các mẫu, ta có thể cập nhật các câu lệnh trả về trong mỗi tuyến mà ta có để trả về các mẫu thay vì văn bản.

Tiếp theo, cập nhật main.py bằng cách sửa đổi dòng nhập và các tuyến cho indexprofile :

project / main.py
from flask import Blueprint, render_template ... @main.route('/') def index():     return render_template('index.html')  @main.route('/profile') def profile():     return render_template('profile.html') 

Đến đây bạn sẽ cập nhật auth.py bằng cách sửa đổi dòng nhập và các tuyến để loginsignup :

project / auth.py
from flask import Blueprint, render_template ... @auth.route('/login') def login():     return render_template('login.html')  @auth.route('/signup') def signup():     return render_template('signup.html') 

Sau khi bạn thực hiện những thay đổi này, đây là giao diện của trang đăng ký nếu bạn chuyển đến /sign-up :

Trang đăng ký tại / signup

Bạn cũng có thể xem các trang cho / , /login/profile .

Ta sẽ để /logout một mình bây giờ vì nó sẽ không hiển thị mẫu khi hoàn tất.

Bước 5 - Tạo mô hình user

Mô hình user của ta thể hiện ý nghĩa của việc ứng dụng của ta có user . Ta sẽ có các trường cho địa chỉ email, password và tên. Trong ứng dụng của bạn , bạn có thể quyết định muốn lưu trữ nhiều thông tin hơn cho mỗi user . Bạn có thể thêm những thứ như sinh nhật, ảnh profile , vị trí hoặc bất kỳ tùy chọn user nào.

Các mô hình được tạo trong Flask-SQLAlchemy được đại diện bởi các lớp sau đó dịch sang các bảng trong database . Các thuộc tính của các lớp đó sau đó chuyển thành các cột cho các bảng đó.

Hãy tiếp tục và tạo mô hình user đó:

  • nano project/models.py

Mã này tạo mô hình user với các cột cho id , email , passwordname :

project / models.py
from . import db  class User(db.Model):     id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy     email = db.Column(db.String(100), unique=True)     password = db.Column(db.String(100))     name = db.Column(db.String(1000)) 

Đến đây bạn đã tạo một mô hình user , bạn có thể chuyển sang cấu hình database của bạn .

Bước 6 - Cấu hình database

Như đã nêu trong Yêu cầu , ta sẽ sử dụng database SQLite. Ta có thể tạo database SQLite của riêng mình, nhưng hãy để Flask-SQLAlchemy làm điều đó cho ta . Ta đã có đường dẫn của database được chỉ định trong file __init__.py , vì vậy ta chỉ cần yêu cầu Flask-SQLAlchemy tạo database trong Python REPL.

Nếu bạn dừng ứng dụng của bạn và mở Python REPL, ta có thể tạo database bằng cách sử dụng phương thức create_all trên đối tượng db . Đảm bảo rằng bạn vẫn ở trong môi trường ảo và trong folder flask_auth_app .

  • from project import db, create_app
  • db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

Lưu ý: Nếu việc sử dụng trình thông dịch Python còn mới đối với bạn, bạn có thể tham khảo tài liệu chính thức .

Đến đây bạn sẽ thấy một file db.sqlite trong folder dự án của bạn. Database này sẽ có bảng user của ta trong đó.

Bước 7 - Cài đặt chức năng ủy quyền

Đối với chức năng đăng ký của ta , ta sẽ lấy dữ liệu mà user nhập vào biểu mẫu và thêm nó vào database của ta . Trước khi thêm nó, ta cần đảm bảo user chưa tồn tại trong database . Nếu không, thì ta cần đảm bảo ta đã băm password trước khi đặt nó vào database vì ta không muốn password của bạn được lưu trữ ở dạng bản rõ.

Hãy bắt đầu bằng cách thêm một hàm thứ hai để xử lý dữ liệu biểu mẫu POST. Trong chức năng này, ta sẽ thu thập dữ liệu được chuyển từ user trước.

Tạo hàm và thêm chuyển hướng xuống dưới cùng. Điều này sẽ cung cấp trải nghiệm user về việc đăng ký thành công và được chuyển đến Trang đăng nhập.

Cập nhật auth.py bằng cách sửa đổi dòng nhập và triển khai signup_post :

project / auth.py
from flask import Blueprint, render_template, redirect, url_for ... @auth.route('/signup', methods=['POST']) def signup_post():     # code to validate and add user to database goes here     return redirect(url_for('auth.login')) 

Bây giờ, hãy thêm phần còn lại của mã cần thiết để đăng ký user .

Để bắt đầu, ta sẽ phải sử dụng đối tượng yêu cầu để lấy dữ liệu biểu mẫu.

Tiếp tục cập nhật auth.py bằng cách thêm nhập và triển khai signup_post :

auth.py
from flask import Blueprint, render_template, redirect, url_for, request from werkzeug.security import generate_password_hash, check_password_hash from .models import User from . import db ... @auth.route('/signup', methods=['POST']) def signup_post():     email = request.form.get('email')     name = request.form.get('name')     password = request.form.get('password')      user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database      if user: # if a user is found, we want to redirect back to signup page so user can try again         return redirect(url_for('auth.signup'))      # create a new user with the form data. Hash the password so the plaintext version isn't saved.     new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))      # add the new user to the database     db.session.add(new_user)     db.session.commit()      return redirect(url_for('auth.login')) 

Lưu ý: Lưu trữ password ở dạng bản rõ được coi là một phương pháp bảo mật kém. Nói chung, bạn cần sử dụng một thuật toán băm phức tạp và một muối password để giữ an toàn cho password .

Bước 8 - Kiểm tra phương pháp đăng ký

Bây giờ ta đã thực hiện xong phương pháp đăng ký, ta sẽ có thể tạo một user mới. Sử dụng biểu mẫu để tạo user .

Có hai cách bạn có thể xác minh xem đăng ký có hiệu quả hay không: bạn có thể sử dụng trình xem database để xem hàng đã được thêm vào bảng của bạn hoặc bạn có thể thử đăng ký lại bằng cùng một địa chỉ email và nếu bạn gặp lỗi , bạn biết email đầu tiên đã được lưu đúng cách. Vì vậy, hãy thực hiện cách tiếp cận đó.

Ta có thể thêm mã để cho user biết email đã tồn tại và yêu cầu họ truy cập trang đăng nhập. Bằng cách gọi hàm flash , ta sẽ gửi một thông báo đến yêu cầu tiếp theo, trong trường hợp này, là chuyển hướng. Trang ta truy cập sau đó sẽ có quyền truy cập vào thông báo đó trong mẫu.

Đầu tiên, ta thêm flash trước khi chuyển hướng trở lại trang đăng ký của bạn .

project / auth.py
from flask import Blueprint, render_template, redirect, url_for, request, flash ... @auth.route('/signup', methods=['POST']) def signup_post():     ...     if user: # if a user is found, we want to redirect back to signup page so user can try again         flash('Email address already exists')         return redirect(url_for('auth.signup')) 

Để nhận được thông báo nhanh trong mẫu, ta có thể thêm mã này vào phía trên biểu mẫu. Điều này sẽ hiển thị thông báo ngay phía trên biểu mẫu.

project / Template / signup.html
... {% with messages = get_flashed_messages() %} {% if messages %}     <div class="notification is-danger">         {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>.     </div> {% endif %} {% endwith %} <form method="POST" action="/signup"> 

Hộp đăng ký hiển thị thông báo "Địa chỉ email đã tồn tại. Đi tới trang đăng nhập" trong hộp màu hồng đậm

Bước 9 - Thêm phương thức đăng nhập

Phương thức đăng nhập tương tự như chức năng đăng ký ở chỗ ta sẽ lấy thông tin user và làm điều gì đó với nó. Trong trường hợp này, ta sẽ so sánh địa chỉ email đã nhập để xem nó có trong database hay không. Nếu vậy, ta sẽ kiểm tra password mà user cung cấp bằng cách băm password mà user chuyển vào và so sánh nó với password đã băm trong database . Ta biết user đã nhập đúng password khi cả hai password băm khớp nhau.

Khi user đã vượt qua kiểm tra password , ta biết rằng họ có thông tin đăng nhập chính xác và ta có thể đăng nhập họ bằng Flask-Login. Bằng cách gọi login_user , Flask-Login sẽ tạo một phiên cho user đó. Phiên này sẽ tồn tại khi user vẫn đăng nhập, điều này sẽ cho phép user xem các trang được bảo vệ.

Ta có thể bắt đầu với một lộ trình mới để xử lý dữ liệu ĐÃ ĐĂNG. Ta sẽ chuyển hướng đến trang profile khi user đăng nhập thành công:

project / auth.py
... @auth.route('/login', methods=['POST']) def login_post():     # login code goes here     return redirect(url_for('main.profile')) 

Bây giờ, ta cần xác minh xem user có thông tin đăng nhập chính xác hay không:

project / auth.py
... @auth.route('/login', methods=['POST']) def login_post():     email = request.form.get('email')     password = request.form.get('password')     remember = True if request.form.get('remember') else False      user = User.query.filter_by(email=email).first()      # check if the user actually exists     # take the user-supplied password, hash it, and compare it to the hashed password in the database     if not user or not check_password_hash(user.password, password):         flash('Please check your login details and try again.')         return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page      # if the above check passes, then we know the user has the right credentials     return redirect(url_for('main.profile')) 

Hãy thêm khối trong mẫu để user có thể nhìn thấy thông báo nhấp nháy. Giống như biểu mẫu đăng ký, hãy thêm thông báo lỗi tiềm ẩn ngay phía trên biểu mẫu:

project / Template / login.html
... {% with messages = get_flashed_messages() %} {% if messages %}     <div class="notification is-danger">         {{ messages[0] }}     </div> {% endif %} {% endwith %} <form method="POST" action="/login"> 

Bây giờ ta có khả năng cho biết user đã đăng nhập thành công, nhưng không có gì để đăng nhập user đó. Đây là nơi ta đưa vào Flask-Login để quản lý các phiên của user .

Trước khi bắt đầu, ta cần một số thứ để Flask-Login hoạt động. Bắt đầu bằng cách thêm UserMixin vào mô hình User của bạn. UserMixin sẽ thêm các thuộc tính Flask-Login vào mô hình để Flask-Login có thể hoạt động với nó.

models.py
from flask_login import UserMixin from . import db  class User(UserMixin, db.Model):     id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy     email = db.Column(db.String(100), unique=True)     password = db.Column(db.String(100))     name = db.Column(db.String(1000)) 

Sau đó, ta cần chỉ định trình tải user của bạn . Trình tải user cho Flask-Login biết cách tìm một user cụ thể từ ID được lưu trữ trong cookie phiên của họ. Ta có thể thêm điều này vào hàm create_app của ta cùng với mã init cho Flask-Login:

project / __ init__.py
... from flask_login import LoginManager ... def create_app():     ...     db.init_app(app)      login_manager = LoginManager()     login_manager.login_view = 'auth.login'     login_manager.init_app(app)      from .models import User      @login_manager.user_loader     def load_user(user_id):         # since the user_id is just the primary key of our user table, use it in the query for the user         return User.query.get(int(user_id)) 

Cuối cùng, ta có thể thêm chức năng login_user ngay trước khi chuyển hướng đến trang profile để tạo phiên:

project / auth.py
from flask_login import login_user from .models import User ... @auth.route('/login', methods=['POST']) def login_post():     ...     # if the above check passes, then we know the user has the right credentials     login_user(user, remember=remember)     return redirect(url_for('main.profile')) 

Với cài đặt Flask-Login, ta có thể sử dụng đường dẫn /login . Khi mọi thứ đã vào đúng vị trí, bạn sẽ thấy trang profile .

Trang profile  có dòng chữ "Chào mừng, Anthony!"

Bước 10 - Bảo vệ trang

Nếu tên của bạn không phải là Anthony , thì bạn sẽ thấy rằng tên của bạn là sai. Những gì ta muốn là profile để hiển thị tên trong database . Vì vậy, trước tiên, ta cần bảo vệ trang và sau đó truy cập vào dữ liệu của user để lấy tên.

Để bảo vệ một trang khi sử dụng Flask-Login, ta thêm trình trang trí @login_requried vào giữa tuyến đường và hàm. Điều này sẽ ngăn user chưa đăng nhập nhìn thấy tuyến đường. Nếu user chưa đăng nhập, user sẽ được chuyển hướng đến trang đăng nhập, theo cấu hình Flask-Login.

Với các tuyến đường được trang trí bằng trình trang trí @login_required , sau đó ta có khả năng sử dụng đối tượng current_user bên trong hàm. current_user này đại diện cho user từ database và ta có thể truy cập tất cả các thuộc tính của user đó bằng ký hiệu dấu chấm . Ví dụ: current_user.email , current_user.passwordcurrent_user.name , và current_user.id sẽ trả về các giá trị thực được lưu trữ trong database cho user đã đăng nhập.

Hãy sử dụng tên của user hiện tại và gửi nó đến mẫu. Sau đó ta sẽ sử dụng tên đó và hiển thị giá trị của nó.

project / main.py
from flask_login import login_required, current_user ... @main.route('/profile') @login_required def profile():     return render_template('profile.html', name=current_user.name) 

Sau đó, trong file profile.html , hãy cập nhật trang để hiển thị giá trị name :

project / Template / profile.html
... <h1 class="title">   Welcome, {{ name }}! </h1> 

Khi ta truy cập trang profile của bạn , ta sẽ thấy tên của user xuất hiện.

Trang chào mừng  user  với tên của  user  hiện đang đăng nhập

Điều cuối cùng ta có thể làm là cập nhật chế độ xem đăng xuất. Ta có thể gọi hàm logout_user trong một lộ trình để đăng xuất. Ta có trình trang trí @login_required vì đăng xuất một user chưa đăng nhập để bắt đầu là không hợp lý.

project / auth.py
from flask_login import login_user, logout_user, login_required ... @auth.route('/logout') @login_required def logout():     logout_user()     return redirect(url_for('main.index')) 

Sau khi đăng xuất và thử xem lại trang profile , ta thấy thông báo lỗi xuất hiện. Điều này là do Flask-Login gửi thông báo cho ta khi user không được phép truy cập một trang.

Trang đăng nhập có thông báo cho biết  user  phải đăng nhập để truy cập trang

Một điều cuối cùng ta có thể làm là đặt if báo cáo trong các mẫu để chỉ hiển thị các liên kết có liên quan đến người sử dụng. Vì vậy, trước khi user đăng nhập, họ sẽ có tùy chọn đăng nhập hoặc đăng ký. Sau khi đăng nhập, họ có thể truy cập profile của bạn hoặc đăng xuất:

Template / base.html
... <div class="navbar-end">     <a href="{{ url_for('main.index') }}" class="navbar-item">         Home     </a>     {% if current_user.is_authenticated %}     <a href="{{ url_for('main.profile') }}" class="navbar-item">         Profile     </a>     {% endif %}     {% if not current_user.is_authenticated %}     <a href="{{ url_for('auth.login') }}" class="navbar-item">         Login     </a>     <a href="{{ url_for('auth.signup') }}" class="navbar-item">         Sign Up     </a>     {% endif %}     {% if current_user.is_authenticated %}     <a href="{{ url_for('auth.logout') }}" class="navbar-item">         Logout     </a>     {% endif %} </div> 

Trang chủ với  chuyển  Trang chủ, Đăng nhập và Đăng ký ở đầu màn hình

Như vậy, bạn đã xây dựng thành công ứng dụng của bạn với xác thực.

Kết luận

Ta đã sử dụng Flask-Login và Flask-SQLAlchemy để xây dựng hệ thống đăng nhập cho ứng dụng của bạn . Ta đã đề cập đến cách xác thực user bằng cách tạo mô hình user trước tiên và lưu trữ thông tin user . Sau đó, ta phải xác minh password của user là chính xác bằng cách băm password từ biểu mẫu và so sánh với password được lưu trữ trong database . Cuối cùng, ta đã thêm quyền cho ứng dụng của bạn bằng cách sử dụng trình trang trí @login_required trên trang profile để chỉ những user đã đăng nhập mới có thể xem trang đó.

Những gì ta đã tạo trong hướng dẫn này sẽ đủ cho các ứng dụng nhỏ hơn, nhưng nếu bạn muốn có nhiều chức năng hơn ngay từ đầu, bạn có thể cần xem xét sử dụng thư viện Flask-User hoặc Flask-Security, cả hai đều được xây dựng trên Thư viện Flask-Đăng nhập.


Tags:

Các tin liên quan