웹사이트 검색

Flask-Login으로 앱에 인증을 추가하는 방법


소개

사용자가 앱에 로그인하도록 허용하는 것은 웹 애플리케이션에 추가할 가장 일반적인 기능 중 하나입니다. Flask-Login 패키지를 사용하여 Flask 앱에 인증을 추가할 수 있습니다.

이 자습서에서는 다음을 수행합니다.

  • 세션 관리를 위해 Flask-Login 라이브러리 사용
  • 비밀번호 해싱을 위해 내장된 Flask 유틸리티 사용
  • 로그인한 사용자만 앱에 보호된 페이지 추가
  • Flask-SQLAlchemy를 사용하여 사용자 모델 생성
  • 사용자가 계정을 만들고 로그인할 수 있도록 가입 및 로그인 양식을 만듭니다.
  • 무언가 잘못되었을 때 사용자에게 다시 플래시 오류 메시지
  • 사용자 계정의 정보를 사용하여 프로필 페이지에 표시

사용자가 로그인하고 보호된 페이지에 액세스할 수 있는 가입 및 로그인 페이지를 구축합니다. 사용자 모델의 정보를 사용하고 사용자가 로그인할 때 보호된 페이지에 표시하여 프로필 모양을 시뮬레이션합니다.

참고: 이 자습서는 범위가 제한되어 있으며 고급 세션 지속에 대해서는 다루지 않습니다. 또한 기본 키의 데이터 유형을 수정하거나 다른 데이터베이스 시스템으로 마이그레이션하기 위한 고려 사항도 이 소개 자습서의 범위를 벗어납니다.

이 프로젝트의 소스 코드는 GitHub에서 사용할 수 있습니다.

전제 조건

이 자습서를 완료하려면 다음이 필요합니다.

  • Python에 대한 약간의 지식.
  • 로컬 환경에 설치된 Python.
  • 기본 Linux 탐색 및 파일 관리에 대한 지식.

다음은 튜토리얼을 완료한 후 프로젝트의 파일 구조가 어떻게 생겼는지 보여 주는 다이어그램입니다.

.
└── flask_auth_app
    └── project
        ├── __init__.py       # setup the app
        ├── auth.py           # the auth routes for the app
        ├── db.sqlite         # the database
        ├── main.py           # the non-auth routes for the app
        ├── models.py         # the 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

자습서를 진행하면서 이러한 디렉토리와 파일을 생성하게 됩니다.

이 튜토리얼은 sqlite3 v3.36.0, python v3.9.8, flask v2.0.2, flask-login 로 확인되었습니다. v0.5.0 및 flask-sqlachemy v2.5.1.

1단계 - 패키지 설치

프로젝트에 필요한 세 가지 주요 패키지가 있습니다.

  • 플라스크
  • Flask-Login: 인증 후 사용자 세션 처리
  • Flask-SQLAlchemy: 데이터베이스와의 인터페이스 및 사용자 모델을 나타냅니다.

데이터베이스에 대한 추가 종속성을 설치하지 않으려면 SQLite를 사용하게 됩니다.

먼저 프로젝트 디렉토리 생성부터 시작합니다.

  1. mkdir flask_auth_app

다음으로 프로젝트 디렉터리로 이동합니다.

  1. cd flask_auth_app

Python 환경이 없는 경우 Python 환경을 만들고 싶을 것입니다.

참고: venv 설정에 대한 로컬 환경 관련 자습서를 참조할 수 있습니다.

컴퓨터에 Python이 설치된 방식에 따라 명령은 다음과 유사합니다.

  1. python3 -m venv auth

-m 플래그는 module-name용입니다. 이 명령은 venv 모듈을 실행하여 auth라는 새로운 가상 환경을 만듭니다. 이렇게 하면 bin, includelib 하위 디렉터리를 포함하는 새 디렉터리가 생성됩니다. 그리고 pyvenv.cfg 파일.

다음으로 다음 명령을 실행합니다.

  1. source auth/bin/activate

이 명령은 가상 환경을 활성화합니다.

가상 환경에서 다음 명령을 실행하여 필요한 패키지를 설치합니다.

  1. pip install flask flask-sqlalchemy flask-login

이제 패키지를 설치했으므로 기본 앱 파일을 만들 준비가 되었습니다.

2단계 - 기본 앱 파일 생성

project 디렉토리를 생성하여 시작하겠습니다.

  1. mkdir project

첫 번째 파일은 프로젝트의 __init__.py 파일입니다.

  1. nano project/__init__.py

이 앱은 청사진과 함께 Flask 앱 팩터리 패턴을 사용합니다. 하나의 청사진은 인덱스 및 보호된 프로필 페이지를 포함하는 일반 경로를 처리합니다. 또 다른 청사진은 인증과 관련된 모든 것을 처리합니다. 실제 앱에서는 원하는 방식으로 기능을 세분화할 수 있지만 여기에서 다루는 솔루션은 이 자습서에서 잘 작동합니다.

이 파일에는 데이터베이스를 초기화하고 청사진을 등록하는 앱을 만드는 기능이 있습니다. 지금은 별로 도움이 되지 않지만 앱의 나머지 부분에 필요할 것입니다.

여기에서 SQLAlchemy를 초기화하고 일부 구성 값을 설정하고 청사진을 등록해야 합니다.

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

이제 기본 앱 파일이 있으므로 경로에 추가를 시작합니다.

3단계 - 경로 추가

경로의 경우 두 개의 청사진을 사용합니다.

main_blueprint의 경우 홈페이지(/)와 프로필 페이지(/profile)가 있습니다.

먼저 main.py를 만듭니다.

  1. nano project/main.py

그런 다음 main_blueprint를 추가합니다.

from flask import Blueprint
from . import db

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return 'Index'

@main.route('/profile')
def profile():
    return 'Profile'

auth_blueprint의 경우 로그인 페이지(/login)와 등록 페이지(/signup)를 검색하는 경로가 있습니다. 마지막으로 활성 사용자를 로그아웃하기 위한 로그아웃 경로(/logout)가 있습니다.

다음으로 auth.py를 만듭니다.

  1. nano project/auth.py

그런 다음 auth_blueprint를 추가합니다.

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'

당분간 login, signuplogout을 텍스트 리턴으로 정의하십시오. 또한 로그인가입의 POST 요청을 처리하기 위한 경로가 있습니다. 나중에 이 코드를 다시 방문하여 원하는 기능으로 업데이트합니다.

터미널에서 FLASK_APPFLASK_DEBUG 값을 설정할 수 있습니다.

  1. export FLASK_APP=project
  2. export FLASK_DEBUG=1

FLASK_APP 환경 변수는 앱을 로드하는 방법을 Flask에 지시합니다. 이것이 create_app이 있는 곳을 가리키기를 원할 것입니다. 이 자습서에서는 project 디렉터리를 가리킵니다.

FLASK_DEBUG 환경 변수는 1로 설정하여 활성화됩니다. 이렇게 하면 브라우저에 애플리케이션 오류를 표시하는 디버거가 활성화됩니다.

flask_auth_app 디렉터리에 있는지 확인한 다음 프로젝트를 실행합니다.

  1. flask run

이제 웹 브라우저에서 5개의 가능한 URL로 이동하여 auth.pymain.py에 정의된 반환된 텍스트를 볼 수 있습니다.

예를 들어 localhost:5000/profile을 방문하면 다음이 표시됩니다. 프로필:

경로가 예상대로 작동하는지 확인했으면 템플릿을 생성할 수 있습니다.

4단계 - 템플릿 만들기

다음으로 앱에서 사용되는 템플릿을 만듭니다. 이것은 실제 로그인 기능을 구현하기 전에 첫 번째 단계입니다.

앱은 4개의 템플릿을 사용합니다.

  • index.html
  • <리>프로필.html\n
  • login.html
  • signup.html

또한 각 페이지에 공통된 코드가 있는 기본 템플릿이 있습니다. 이 경우 기본 템플릿에는 탐색 링크와 페이지의 일반 레이아웃이 있습니다.

먼저 project 디렉터리 아래에 templates 디렉터리를 만듭니다.

  1. mkdir -p project/templates

그런 다음 base.html을 만듭니다.

  1. nano project/templates/base.html

다음으로 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>

이 코드는 애플리케이션의 각 페이지에 대한 일련의 메뉴 링크를 생성합니다. 또한 하위 템플릿으로 덮어쓸 수 있는 콘텐츠에 대한 블록을 설정합니다.

참고: 이 튜토리얼은 공식 Bulma 문서를 사용합니다.

다음으로 templates/index.html을 만듭니다.

  1. nano project/templates/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 %}

이 코드는 제목과 부제가 포함된 기본 색인 페이지를 생성합니다.

다음으로 templates/login.html을 만듭니다.

  1. nano project/templates/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" name="remember">
                    Remember me
                </label>
            </div>
            <button class="button is-block is-info is-large is-fullwidth">Login</button>
        </form>
    </div>
</div>
{% endblock %}

다음으로 templates/signup.html을 만듭니다.

  1. nano project/templates/signup.html

다음 코드를 추가하여 email, namepassword에 대한 필드가 있는 등록 페이지를 만듭니다.

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

다음으로 templates/profile.html을 만듭니다.

  1. nano project/templates/profile.html

이 코드를 추가하여 Anthony를 환영하도록 하드코딩된 제목이 있는 페이지를 만듭니다.

{% extends "base.html" %}

{% block content %}
<h1 class="title">
  Welcome, Anthony!
</h1>
{% endblock %}

나중에 이 코드를 다시 방문하여 모든 사용자에게 동적으로 인사할 것입니다.

템플릿을 추가한 후에는 각 경로의 return 문을 업데이트하여 텍스트 대신 템플릿을 반환할 수 있습니다.

다음으로 indexprofile에 대한 가져오기 행과 경로를 수정하여 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')

이제 loginsignup에 대한 가져오기 행과 경로를 수정하여 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')

이렇게 변경한 후 /signup으로 이동하면 가입 페이지가 다음과 같이 표시됩니다.

/, /login/profile 페이지로 이동할 수도 있습니다.

나중에 템플릿을 표시하지 않으므로 지금은 /logout을 그대로 두십시오.

5단계 - 사용자 모델 만들기

사용자 모델은 앱에 사용자가 있다는 것이 의미하는 바를 나타냅니다. 이 자습서에서는 이메일 주소, 암호이름에 대한 필드가 필요합니다. 향후 애플리케이션에서는 사용자당 훨씬 더 많은 정보를 저장하기를 원할 수 있습니다. 생일, 프로필 사진, 위치 또는 사용자 기본 설정과 같은 항목을 추가할 수 있습니다.

Flask-SQLAlchemy에서 생성된 모델은 데이터베이스의 테이블로 변환되는 클래스로 표현됩니다. 그러면 해당 클래스의 속성이 해당 테이블의 열로 바뀝니다.

사용자 모델을 생성합니다.

  1. nano 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))

이 코드는 id, 이메일, 비밀번호이름에 대한 열이 있는 사용자를 정의합니다. 코드>.

이제 사용자 모델을 만들었으므로 데이터베이스 구성으로 이동할 수 있습니다.

6단계 - 데이터베이스 구성

SQLite 데이터베이스를 사용하게 됩니다. 직접 SQLite 데이터베이스를 생성할 수 있지만 Flask-SQLAlchemy가 대신 수행하도록 합시다. __init__.py 파일에 지정된 데이터베이스 경로가 이미 있으므로 Flask-SQLAlchemy에 Python REPL에서 데이터베이스를 생성하도록 지시해야 합니다.

여전히 가상 환경과 flask_auth_app 디렉터리에 있는지 확인합니다.

앱을 중지하고 Python REPL을 열면 db 개체에서 create_all 메서드를 사용하여 데이터베이스를 만들 수 있습니다.

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

참고: Python 인터프리터를 처음 사용하는 경우 공식 문서를 참조할 수 있습니다.

이제 프로젝트 디렉터리에 db.sqlite 파일이 표시됩니다. 이 데이터베이스에는 사용자 테이블이 있습니다.

7단계 - 인증 기능 설정

가입 기능의 경우 사용자가 양식에 제출한 데이터를 데이터베이스에 추가합니다. 동일한 이메일 주소를 가진 사용자가 데이터베이스에 이미 존재하지 않는지 확인해야 합니다. 존재하지 않는 경우 암호를 데이터베이스에 넣기 전에 해시했는지 확인해야 합니다.

참고: 암호를 일반 텍스트로 저장하는 것은 좋지 않은 보안 관행으로 간주됩니다. 일반적으로 암호를 안전하게 유지하려면 복잡한 해싱 알고리즘과 솔트가 필요합니다.

POST 양식 데이터를 처리하는 두 번째 함수를 추가하여 시작하겠습니다. 사용자로부터 전달된 데이터를 수집합니다.

가져오기 행을 수정하고 signup_post를 구현하여 auth.py를 업데이트합니다.

from flask import Blueprint, render_template, redirect, url_for
...
@auth.route('/signup')
def signup():
    return render_template('signup.html')

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

함수를 만들고 리디렉션을 추가합니다. 이것은 성공적으로 가입하고 로그인 페이지로 이동하는 사용자 경험을 제공합니다.

이제 사용자 등록에 필요한 나머지 코드를 추가해 보겠습니다. 요청 객체를 사용하여 양식 데이터를 가져옵니다.

가져오기를 추가하고 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():
    # code to validate and add user to database goes here
    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'))

이 코드는 동일한 이메일 주소를 가진 사용자가 데이터베이스에 존재하는지 확인합니다.

8단계 - 가입 방법 테스트

이제 가입 방법이 완료되었으므로 새 사용자를 만들 수 있습니다. 사용자를 만들기 위해 양식을 테스트해 봅시다.

가입이 성공했는지 확인할 수 있는 두 가지 방법이 있습니다.

  • 데이터베이스 뷰어를 사용하여 테이블에 추가된 행을 볼 수 있습니다.
  • 또는 동일한 이메일 주소로 다시 가입을 시도하고 오류가 발생하면 첫 번째 이메일이 제대로 저장된 것입니다.

사용자에게 이메일이 이미 있음을 알리고 로그인 페이지로 이동하도록 지시하는 코드를 추가해 보겠습니다. flash 함수를 호출하면 다음 요청(이 경우 리디렉션)에 메시지를 보낼 수 있습니다. 그러면 사용자가 리디렉션되는 페이지는 템플릿의 해당 메시지에 액세스할 수 있습니다.

먼저 가입 페이지로 리디렉션하기 전에 플래시를 추가하세요.

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

템플릿에서 깜박이는 메시지를 얻으려면 양식 앞에 이 코드를 추가할 수 있습니다.

...
{% 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">

이 코드는 이메일 주소가 이미 데이터베이스에 있는 경우 \이메일 주소가 이미 존재합니다. 로그인 페이지로 이동하십시오.\ 메시지를 표시합니다.

이 시점에서 애플리케이션을 실행하고 이미 존재하는 이메일 주소로 가입을 시도할 수 있습니다.

9단계 - 로그인 방법 추가

로그인 방법은 회원가입 기능과 유사합니다. 이 경우 입력한 이메일 주소를 비교하여 데이터베이스에 있는지 확인합니다. 그렇다면 사용자가 전달한 암호를 해싱하고 이를 데이터베이스의 해싱된 암호와 비교하여 사용자가 제공한 암호를 테스트합니다. . 해시된 비밀번호가 모두 일치하면 사용자가 올바른 비밀번호를 입력했음을 알 수 있습니다.

사용자가 비밀번호 확인을 통과하면 올바른 자격 증명이 있음을 알게 되며 Flask-Login을 사용하여 로그인할 수 있습니다. login_user를 호출하면 Flask-Login은 사용자가 로그인 상태를 유지하는 동안 지속되는 해당 사용자에 대한 세션을 생성하여 사용자가 보호된 페이지를 볼 수 있도록 합니다.

POST로 제출된 데이터를 처리하기 위한 새로운 경로로 시작할 수 있습니다. 사용자가 성공적으로 로그인하면 프로필 페이지로 리디렉션됩니다.

...
@auth.route('/login')
def login():
    return render_template('login.html')

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

이제 사용자에게 올바른 자격 증명이 있는지 확인해야 합니다.

...
@auth.route('/login', methods=['POST'])
def login_post():
    # login code goes here
    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'))

사용자가 깜박이는 메시지를 볼 수 있도록 템플릿에 블록을 추가해 보겠습니다.

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

이제 사용자가 성공적으로 로그인했다고 말할 수 있지만 사용자를 로그인할 수 있는 항목이 없습니다.

Flask-Login은 사용자 세션을 관리할 수 있습니다. 사용자 모델에 UserMixin을 추가하여 시작하십시오. UserMixin은 모델에 Flask-Login 속성을 추가하여 Flask-Login이 작업할 수 있도록 합니다.

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

그런 다음 사용자 로더를 지정해야 합니다. 사용자 로더는 세션 쿠키에 저장된 ID에서 특정 사용자를 찾는 방법을 Flask-Login에 알려줍니다. Flask-Login을 위한 init 코드와 함께 create_app 함수에 다음을 추가합니다.

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
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))

마지막으로 세션을 생성하기 위해 프로필 페이지로 리디렉션하기 전에 login_user 함수를 추가합니다.

from flask_login import login_user
from .models import User
from . import db
...
@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'))

Flask-Login 설정에서는 /login 경로를 사용합니다. 모든 것이 제자리에 있으면 프로필 페이지가 표시됩니다.

이 시점에서 애플리케이션을 실행하고 로그인을 시도할 수 있습니다.

10단계 - 페이지 보호

귀하의 이름이 Anthony가 아닌 경우 프로필 페이지에서 귀하의 이름이 잘못되었음을 알 수 있습니다. 목표는 프로필이 데이터베이스에 이름을 표시하는 것입니다. 이름을 얻으려면 페이지를 보호한 다음 사용자 데이터에 액세스해야 합니다.

Flask-Login을 사용할 때 페이지를 보호하려면 경로와 함수 사이에 @login_requried 데코레이터를 추가하세요. 이렇게 하면 로그인하지 않은 사용자가 경로를 볼 수 없습니다. 사용자가 로그인하지 않은 경우 사용자는 Flask 로그인 구성에 따라 로그인 페이지로 리디렉션됩니다.

@login_required 데코레이터로 장식된 경로를 사용하면 함수 내에서 current_user 개체를 사용할 수 있습니다. 이 current_user는 데이터베이스의 사용자를 나타내며 점 표기법으로 해당 사용자의 모든 속성에 대한 액세스를 제공합니다. 예를 들어 current_user.email, current_user.password, current_user.namecurrent_user.id가 반환됩니다. 로그인한 사용자에 대해 데이터베이스에 저장된 실제 값.

current_username을 사용하여 템플릿으로 전송해 보겠습니다.

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

그런 다음 profile.html 파일에서 페이지를 업데이트하여 name 값을 표시합니다.

...
<h1 class="title">
  Welcome, {{ name }}!
</h1>

사용자가 프로필 페이지를 방문하면 이름이 표시됩니다.

이제 로그아웃 보기를 업데이트하려면 로그아웃 경로에서 logout_user 함수를 호출하십시오.

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

처음부터 로그인하지 않은 사용자를 로그아웃하는 것은 의미가 없으므로 @login_required 데코레이터를 사용하십시오.

사용자가 로그아웃하고 프로필 페이지를 다시 보려고 하면 오류 메시지가 표시됩니다.

Flask-Login은 사용자가 페이지에 액세스할 수 없을 때 메시지를 표시하기 때문입니다.

마지막으로 할 일은 템플릿에 if 문을 넣어 사용자와 관련된 링크만 표시하는 것입니다.

...
<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>

사용자는 로그인하기 전에 로그인하거나 가입할 수 있는 옵션이 있습니다. 로그인한 후 프로필로 이동하거나 로그아웃할 수 있습니다.

이를 통해 인증을 사용하여 앱을 성공적으로 빌드했습니다.

결론

이 자습서에서는 Flask-Login 및 Flask-SQLAlchemy를 사용하여 앱의 로그인 시스템을 구축했습니다. 먼저 사용자 모델을 만들고 사용자 정보를 저장하여 사용자를 인증하는 방법을 다루었습니다. 그런 다음 양식에서 비밀번호를 해시하고 데이터베이스에 저장된 비밀번호와 비교하여 사용자의 비밀번호가 올바른지 확인해야 했습니다. 마지막으로 로그인한 사용자만 해당 페이지를 볼 수 있도록 프로필 페이지에서 @login_required 데코레이터를 사용하여 앱에 권한을 추가했습니다.

이 튜토리얼에서 만든 것은 소규모 앱에 충분하지만 처음부터 더 많은 기능을 갖고 싶다면 Flask-User 또는 Flask-Security 라이브러리를 사용하는 것이 좋습니다. Flask-로그인 라이브러리.