source

플라스크 마개: 어떻게 작동하는지 이해할 수 없습니다.

factcode 2022. 11. 26. 13:54
반응형

플라스크 마개: 어떻게 작동하는지 이해할 수 없습니다.

어떻게 작동하는지 이해하려고 노력 중이야

문서에서 미리 입력된 사용자 목록을 사용하고 있는 것을 알 수 있습니다.데이터베이스에 저장된 사용자 목록을 가지고 놀고 싶습니다.

다만, 이 모듈의 내용을 이해할 수 없는 것이 있습니다.

@login_manager.user_loader
def load_user(userid):
    #print 'this is executed',userid
    return user(userid, 'asdf')

이 코드는 요청 시마다 호출됩니까?사용자 개체의 모든 세부 정보를 로드하는 데 사용됩니까?

지금으로서는, 다음과 같은 코드가 있습니다.

@app.route('/make-login')
def make_login():
    username = 'asdf'
    password = 'asdf'
    user_data = authenticate(username, password)
    user_obj = user(user_data[0], user_data[1])
    login_user(user_obj)
    return render_template('make-login.html')

/make-login에 접속하면 로그인하고 싶습니다.

내 사용자 클래스:

class user(object):
    def __init__(self, id, username, active=True):
        self.username = username
        self.id = id
        #self.active = active
    def is_authenticated(self):
        return True  

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return 5

또한 인증/등록을 위한 두 가지 기능을 추가로 작성했습니다.

def authenticate(username, password):

    cursor = db.cursor()
    password = md5.md5(password).hexdigest()
    try:
        query = "SELECT * FROM `users` WHERE `username` = %s AND `password` = %s"
        cursor.execute(query, (username, password))
        results = cursor.fetchall()
        #print results[0][0]
        #print "here i am"
        if not results:
            return False
        else:
            user_data = [results[0][0], results[0][1]]
            return user_data
            #self.authenticated = True
            #self.user_id = results[0][0]
            #session['username']  = results['username']
            #print type(results)
    except db.Error, e:
        return 'There was a mysql error'    

def register(username, password, email, *args):
    cursor = db.cursor()
    password = md5.md5(password).hexdigest()
    try:
        #query = "INSERT INTO `users` (`username`, `password`, `email`) VALUES ('%s', '%s', '%s')" % (username, password, email)
        query = "INSERT INTO `users` (`username`, `password`, `email`) VALUES (%s, %s, %s)"
        cursor.execute(query, (username, password, email))
        db.commit()
        return True
    except db.Error, e:
        print 'An error has been passed. %s' %e
        db.rollback()
        return False

MySQL에서 어떻게 동작하는지 모르겠어요.또한 사용자가 로그인했는지 알 수 없습니다.사용자 ID 또는 사용자 이름을 얻으려면 어떻게 해야 하나요?

이게 어떻게 작동하는지 설명해 줄 사람?

Flask-login에는 실제로 사용자 백엔드가 없습니다.사용자의 로그인과 로그아웃을 지원하기 위해 세션 머신을 처리합니다.유저가 「액티브」인지 아닌지를 파악하는 방법( 「액티브」는 애플리케이션 마다 다른 것을 의미할 수 있기 때문에)은, 유저를 나타내는 것, 및 유저의 「액티브」인지 아닌지를 판단하는 방법에 의해서, 유저에게 지시할 필요가 있습니다.

매뉴얼을 읽고 그 기능과 기능을 확인해야 합니다.여기서는 db 백엔드를 사용한 배선에만 초점을 맞춥니다.

먼저 사용자의 속성을 나타내는 사용자 개체를 정의합니다.이 오브젝트는 데이터베이스, LDAP 등의 쿼리를 실행할 수 있으며 로그인 메커니즘과 데이터베이스 백엔드를 연결하는 후크입니다.

이 목적으로 로그인 예제 스크립트를 사용합니다.

class User(UserMixin):
    def __init__(self, name, id, active=True):
        self.name = name
        self.id = id
        self.active = active

    def is_active(self):
        # Here you should write whatever the code is
        # that checks the database if your user is active
        return self.active

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True

사용자 오브젝트가 생성되면 사용자를 로드하는 메서드를 작성해야 합니다(기본적으로 사용자 오브젝트의 인스턴스를 만듭니다).User위로부터의 클래스).이 메서드는 사용자 ID로 호출됩니다.

@login_manager.user_loader
def load_user(id):
     # 1. Fetch against the database a user by `id` 
     # 2. Create a new object of `User` class and return it.
     u = DBUsers.query.get(id)
    return User(u.name,u.id,u.active)

다음의 순서를 실행하면, 로그인 방법에 의해서 다음과 같이 됩니다.

  1. 사용자 이름과 비밀번호가 (데이터베이스와) 일치하는지 확인합니다. 이 코드를 직접 작성해야 합니다.

  2. 인증에 성공한 경우 사용자의 인스턴스를 다음 주소로 전달합니다.login_user()

Flask-login은 모든 요청 전에 사용자를 로드하려고 시도합니다.네, 아래의 예제 코드는 모든 요청 전에 호출됩니다.현재 세션에 어떤 사용자 ID가 있는지 확인하고 해당 ID의 사용자 개체를 로드합니다.

@login_manager.user_loader
def load_user(userid):
    #print 'this is executed',userid
    return user(userid, 'asdf')        

github의 Flask-login 소스 코드를 보면 함수 init_app 아래에 다음과 같은 행이 있습니다.

app.before_request(self._load_user)

따라서 모든 요구 전에 _load_user 함수가 호출됩니다._load_user 함수는 실제로 조건에 따라 다른 함수 "reload_user()"를 호출합니다.마지막으로 reload_user() 함수는 작성한 콜백 함수(예에서는 load_user())를 호출합니다.

또한 플라스크 로그인은 사용자를 로그인/로그아웃하는 메커니즘만 제공합니다.mysql 데이터베이스를 사용해도 상관없습니다.

Flask-Login 문서에 따라 사용자 개체를 반환해야 하며 사용자 ID를 찾을 수 없는 경우 Exception 대신 None을 반환해야 합니다.

@login_manager.user_loader
def load_user(userid):
    try:
        #: Flask Peewee used here to return the user object
        return User.get(User.id==userid)
    except User.DoesNotExist:
        return None

Flask-Security를 사용하면 데이터베이스 접근을 위해 Flask-Login과 SQL Chemy를 결합하여 사용자 레코드의 백엔드 처리를 대부분 자동화할 수 있습니다.

빠른 시작 튜토리얼을 통해 시작할 수 있습니다.app.config[']를 설정합니다.SQLALCHEMY_DATABASE_URI']를 MySQL 데이터베이스 연결 문자열에 연결합니다.

모든 설명이 끝나면 코드를 사용하여 간단한 사용 예를 제시함과 동시에 아래에 답변하겠습니다.

다음의 순서를 실행하면, 로그인 방법에 의해서 다음과 같이 됩니다.

  1. 사용자 이름과 비밀번호가 (데이터베이스와) 일치하는지 확인합니다. 이 코드를 직접 작성해야 합니다.
  2. 는, 를 「인스턴스」에 합니다.login_user()

예를 들어 다음과 같이 프로젝트의 구조를 나타냅니다.

├─stackoverflow
  │   run.py
  │
  └───site
      │   forms.py
      │   models.py
      │   routes.py
      │   site.db
      │   __init__.py
      │
      ├───static
      │       main.css
      │
      └───templates
              about.html
              account.html
              home.html
              layout.html
              login.html
              register.html

가장 관심이 있는 것은 모델입니다.

# models.py
from site import db, login_manager
from flask_login import UserMixin


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
    password = db.Column(db.String(60), nullable=False)

    def __repr__(self):
        return f"User('{self.username}', '{self.email}', '{self.image_file}')"

그리고 사용자 로그인으로 호출합니다.정확히는 사용자가 등록한 후에 호출합니다.사용자가 존재하는 후에 호출합니다.

구체적으로는, 실장할 필요가 있는 2개의 스텝에 대한 대답은, 다음의 2 행의 코드에서 확인할 수 있습니다.

  1. 사용자 이름과 비밀번호가 (데이터베이스와) 일치하는지 확인합니다. 이 코드를 직접 작성해야 합니다.

::if user and bcrypt.check_password_hash(user.password, form.password.data):

  1. 는, 를 「인스턴스」에 합니다.login_user()

::login_user(user, remember=form.remember.data)

# routes.py

from flask import render_template, url_for, flash, redirect, request
from site import app, db, bcrypt
from site.forms import RegistrationForm, LoginForm
from site.models import User
from flask_login import login_user, current_user, logout_user, login_required



@app.route("/")
@app.route("/home")
def home():
    return render_template('home.html', title="Welcome")


@app.route("/register", methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    form = RegistrationForm()
    if form.validate_on_submit():
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
        user = User(username=form.username.data, email=form.email.data, password=hashed_password)
        db.session.add(user)
        db.session.commit()
        flash('Your account has been created! You are now able to log in', 'success')
        return redirect(url_for('login'))
    return render_template('register.html', title='Register', form=form)


@app.route("/login", methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            return redirect(next_page) if next_page else redirect(url_for('home'))
        else:
            flash('Login Unsuccessful. Please check email and password', 'danger')
    return render_template('login.html', title='Login', form=form)


# Views that require your users to be logged in can be decorated with the `login_required` decorator

@app.route("/account")
@login_required
def account():
    return render_template('account.html', title='Account')


# When the user is ready to log out:

@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))

는 로그인한 사용자에게 할 수 .current_user「 」 「 」 、 「 」 、 「 」 。

{% if current_user.is_authenticated %}
  Hi {{ current_user.username }}!
{% endif %}

을 했을 때login_requiredFlask-Login 401 오류와 중단됩니다.)

은 '로그인하다'로 설정할 수.LoginManager.login_view:

login_manager.login_view = 'login'

# __init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager

app = Flask(__name__)
app.config['SECRET_KEY'] = 'ENTER_SECRET_KEY'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'

from site import routes

마지막으로 프로젝트를 실행합니다.

# run.py

from site import app

if __name__ == '__main__':
    app.run(debug=True)

훌륭한 설명에 덧붙여, 이 간단한 예가 도움이 되었으면 합니다.

다음 Flask의 로그인 사용 예를 나타냅니다.https://bitbucket.org/leafstorm/flask-login/src/3160dbfc7cfc/example/login-example.py 로그인이 필요한 모든 메서드에 대해 @syslog_required를 사용해야 합니다.예를들면,

@app.route('/make-login')
@login_required
def make_login():
    ...

flask-login은 user_loader를 호출하여 요청별로 사용자 개체를 요구합니다.

매번 DB를 사용하면 성능 저하를 기대할 수 있습니다.(이 때문에 문제가 있는 답변)

한편, 로그인 루트는 세션 중에1번밖에 호출되지 않습니다.

따라서 일반적인 (세션 기반) 구현은 다음과 같습니다.

  • /login 경로로 DB에서 데이터를 가져와 세션에서 캐시합니다.
  • user_loader의 캐시에서 사용자를 로드합니다.

다음과 같은 경우:

@app.route("/login")
def login_callback():
    user_data=my_fetch_from_db_based_on_whatever()
    if my_check_credentials_ok(user_data)
        session["user"]=user_data
        login_user(User(user_data))
    else:
        abort(400)
 :

@login_manager.user_loader
def load_user(user_id):
    user_data = session["user"]
    user=User(user_data)
    return user if user.userid==user_id else None

언급URL : https://stackoverflow.com/questions/12075535/flask-login-cant-understand-how-it-works

반응형