찾다
백엔드 개발파이썬 튜토리얼Python의 Flask 프레임워크 양식 플러그인 Flask-WTF를 사용하여 웹 로그인 확인 구현

양식은 사용자가 웹 애플리케이션과 상호 작용할 수 있게 해주는 기본 요소입니다. Flask 자체는 양식에 도움이 되지 않지만 Flask-WTF 확장을 사용하면 Flask 애플리케이션에서 널리 사용되는 WTForms 패키지를 사용할 수 있습니다. 이 패키지를 사용하면 양식을 정의하고 제출물을 더 쉽게 처리할 수 있습니다.

플라스크-WTF
Flask-WTF(설치 후 GitHub 프로젝트 페이지: https://github.com/lepture/flask-wtf)로 가장 먼저 하고 싶은 일은 myapp.forms 패키지에 양식을 정의하는 것입니다.

# ourapp/forms.py

from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Email

class EmailPasswordForm(Form):
 email = StringField('Email', validators=[DataRequired(), Email()])
 password = PasswordField('Password', validators=[DataRequired()])

Flask-WTF 버전 0.9 이전에는 Flask-WTF가 WTForms 필드 및 유효성 검사기에 대한 자체 패키징을 제공했습니다. wtforms 대신 플라스크.ext.wtforms에서 TextField 및 PasswordField를 가져오는 코드가 외부에 많이 표시될 수 있습니다.
Flask-WTF 버전 0.9 이후에는 이러한 필드와 유효성 검사기를 wtforms에서 직접 가져와야 합니다.
우리가 정의하는 양식은 사용자 로그인 양식입니다. 이를 EmailPasswordForm()이라고 부르며, 이 동일한 양식 클래스(양식)를 재사용하여 등록 양식과 같은 다른 작업을 수행할 수 있습니다. 여기서는 길고 쓸모없는 형식을 정의하지 않고 매우 일반적으로 사용되는 형식을 선택하여 Flask-WTF를 사용하여 형식을 정의하는 방법을 소개합니다. 어쩌면 특히 복잡한 형태가 미래의 공식 프로젝트에서 정의될 수도 있습니다. 필드 이름이 포함된 양식의 경우 양식 내에서 명확하고 고유한 이름을 사용하는 것이 좋습니다. 긴 형식의 경우 위와 더 일치하는 필드 이름을 제공해야 할 수도 있습니다.

로그인 양식을 사용하면 몇 가지 작업을 수행할 수 있습니다. CSRF 취약성으로부터 애플리케이션을 보호하고, 사용자 입력의 유효성을 검사하며, 양식에 대해 정의한 필드에 대한 적절한 마크업을 렌더링합니다.

CSRF 보호 및 검증
CSRF는 Cross-Site Request Forgery의 약자입니다. CSRF 공격은 제3자가 애플리케이션 서버에 대한 요청(예: 양식 제출)을 위조할 때 발생합니다. 취약한 서버는 양식의 데이터가 자체 웹사이트에서 온 것으로 가정하고 그에 따라 행동합니다.

예를 들어 이메일 제공업체에서 양식을 제출하여 계정을 삭제할 수 있다고 가정해 보겠습니다. 양식은 서버의 account_delete 끝점에 POST 요청을 보내고 양식이 제출되면 로그인된 계정을 삭제합니다. 동일한 account_delete 엔드포인트에 POST 요청을 보내는 양식을 웹사이트에서 생성할 수 있습니다. 이제 누군가가 양식에서 제출 버튼을 클릭하도록 하면(또는 JavaScript를 통해 클릭하면) 이메일 공급자가 제공한 로그인이 제거됩니다. 물론 이메일 제공업체는 웹사이트에서 양식 제출이 이루어지지 않는다는 사실을 아직 모릅니다.

그렇다면 다른 웹사이트에서 POST 요청이 들어오는 것을 어떻게 방지할 수 있나요? WTForms는 각 양식을 렌더링할 때 고유한 토큰을 생성함으로써 이를 가능하게 합니다. 생성된 토큰은 POST 요청의 데이터와 함께 서버로 다시 전달되며 양식을 수락하기 전에 서버에서 토큰의 유효성을 검사해야 합니다. 중요한 점은 토큰이 사용자 세션(쿠키)에 저장된 값과 연결되어 있으며 특정 시간(기본값은 30분) 후에 만료된다는 것입니다. 이렇게 하면 유효한 양식을 제출한 사람이 페이지를 로드한 사람과 동일하고(또는 적어도 동일한 컴퓨터를 사용하는 동일한 사람) 페이지 로드 후 30분 이내에만 제출할 수 있음을 보장할 수 있습니다.

Flask-WTF로 CSRF 보호를 시작하려면 로그인 페이지에 대한 보기를 정의해야 합니다.

# ourapp/views.py

from flask import render_template, redirect, url_for

from . import app
from .forms import EmailPasswordForm

@app.route('/login', methods=["GET", "POST"])
def login():
 form = EmailPasswordForm()
 if form.validate_on_submit():

  # Check the password and log the user in
  # [...]

  return redirect(url_for('index'))
 return render_template('login.html', form=form)

양식이 제출되고 확인되면 로그인 로직을 계속 진행할 수 있습니다. 제출되지 않은 경우(예: GET 요청) 렌더링할 수 있도록 양식 개체를 템플릿에 전달해야 합니다. CSRF 보호를 사용할 때 템플릿의 모양은 다음과 같습니다.

{# ourapp/templates/login.html #}

{% extends "layout.html" %}
{% endraw %}
<html>
 <head>
  <title>Login Page</title>
 </head>
 <body>
  <form action="{{ url_for('login') }}" method="post">
   <input type="text" name="email" />
   <input type="password" name="password" />
   {{ form.csrf_token }}
  </form>
 </body>
</html>

{% raw %}{{ form.csrf_token }}{% endraw %}는 멋진 CSRF 토큰이 포함된 숨겨진 필드를 렌더링하고 WTForms가 양식을 확인할 때 검색됩니다. 토큰을 처리하기 위한 로직을 포함하는 것에 대해 걱정할 필요가 없습니다. WTForms가 우리를 위해 사전에 이를 수행해 줄 것입니다. 만세!

맞춤 검증
WTForms에서 제공하는 내장 양식 유효성 검사기(예: 필수(), 이메일() 등) 외에도 자체 유효성 검사기를 만들 수 있습니다. 데이터베이스를 확인하고 사용자가 제공한 값이 데이터베이스에 존재하지 않는지 확인하는 Unique() 유효성 검사기를 작성하여 자신만의 유효성 검사기를 만드는 방법을 설명하겠습니다. 이는 사용자 이름이나 이메일 주소가 이미 사용되고 있지 않은지 확인하는 데 사용될 수 있습니다. WTForms가 없으면 뷰에서 이러한 작업을 수행해야 할 수도 있지만 이제는 양식 자체에서 작업을 수행할 수 있습니다.

이제 간단한 등록 양식을 정의해 보겠습니다. 사실 이 양식은 로그인 양식과 거의 동일합니다. 나중에 일부 사용자 정의 유효성 검사기를 추가할 것입니다.

# ourapp/forms.py

from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Email

class EmailPasswordForm(Form):
 email = StringField('Email', validators=[DataRequired(), Email()])
 password = PasswordField('Password', validators=[DataRequired()])

现在我们要添加我们的验证器用来确保它们提供的邮箱地址不存在数据库中。我们把这个验证器放在一个新的 util 模块,util.validators。

# ourapp/util/validators.py
from wtforms.validators import ValidationError

class Unique(object):
 def __init__(self, model, field, message=u'This element already exists.'):
  self.model = model
  self.field = field

 def __call__(self, form, field):
  check = self.model.query.filter(self.field == field.data).first()
  if check:
   raise ValidationError(self.message)

这个验证器假设我们是使用 SQLAlchemy 来定义我们的模型。WTForms 期待验证器返回某种可调用的对象(例如,一个可调用的类)。

在 Unique() 的 \_\_init\_\_ 中我们可以指定哪些参数传入到验证器中,在本例中我们要传入相关的模型(例如,在我们例子中是传入 User 模型)以及要检查的字段。当验证器被调用的时候,如果定义模型的任何实例匹配表单中提交的值,它将会抛出一个 ValidationError。我们也可以添加一个具有通用默认值的消息,它将会被包含在 ValidationError 中。

现在我们可以修改 EmailPasswordForm,使用我们自定义的 Unique 验证器。

# ourapp/forms.py

from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired

from .util.validators import Unique
from .models import User

class EmailPasswordForm(Form):
 email = StringField('Email', validators=[DataRequired(), Email(),
  Unique(
   User,
   User.email,
   message='There is already an account with that email.')])
 password = PasswordField('Password', validators=[DataRequired()])

渲染表单
WTForms 也能帮助我们为表单渲染成 HTML 表示。WTForms 实现的 Field 字段能够渲染成该字段的 HTML 表示,所以为了渲染它们,我们只必须在我们模板中调用表单的字段。这就像渲染 csrf_token 字段。下面给出了一个登录模板的示例,在里面我们使用 WTForms 来渲染我们的字段。

{# ourapp/templates/login.html #}

{% extends "layout.html" %}
<html>
 <head>
  <title>Login Page</title>
 </head>
 <body>
  <form action="" method="post">
   {{ form.email }}
   {{ form.password }}
   {{ form.csrf_token }}
  </form>
 </body>
</html>

我们可以自定义如何渲染字段,通过传入字段的属性作为参数到调用中。

<form action="" method="post">
 {{ form.email.label }}: {{ form.email(placeholder='yourname@email.com') }}
 <br>
 {% raw %}{{ form.password.label }}: {{ form.password }}{% endraw %}
 <br>
 {% raw %}{{ form.csrf_token }}{% endraw %}
</form>

处理 OpenID 登录
现实生活中,我们发现有很多人都不知道他们拥有一些公共账号。一部分大牌的网站或服务商都会为他们的会员提供公共账号的认证。举个栗子,如果你有一个 google 账号,其实你就有了一个公共账号,类似的还有 Yahoo, AOL, Flickr 等。
为了方便我们的用户能简单的使用他们的公共账号,我们将把这些公共账号的链接添加到一个列表,这样用户就不用自手工输入了。

我们要把一些提供给用户的公共账号服务商定义到一个列表里面,这个列表就放到配置文件中吧 (fileconfig.py):

CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'
 
OPENID_PROVIDERS = [
 { 'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id' },
 { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' },
 { 'name': 'AOL', 'url': 'http://openid.aol.com/<username>' },
 { 'name': 'Flickr', 'url': 'http://www.flickr.com/<username>' },
 { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]

接下来就是要在我们的登录视图函数中使用这个列表了:

@app.route('/login', methods = ['GET', 'POST'])
def login():
 form = LoginForm()
 if form.validate_on_submit():
  flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data))
  return redirect('/index')
 return render_template('login.html',
  title = 'Sign In',
  form = form,
  providers = app.config['OPENID_PROVIDERS'])

我们从 app.config 中引入了公共账号服务商的配置列表,然后把它作为一个参数通过 render_template 函数引入到模板。

接下来要做的我想你也猜得到,我们需要在登录模板中把这些服务商链接显示出来。

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<script type="text/javascript">
function set_openid(openid, pr)
{
 u = openid.search('<username>')
 if (u != -1) {
  // openid requires username
  user = prompt('Enter your ' + pr + ' username:')
  openid = openid.substr(0, u) + user
 }
 form = document.forms['login'];
 form.elements['openid'].value = openid
}
</script>
<h1 id="Sign-In">Sign In</h1>
<form action="" method="post" name="login">
 {{form.hidden_tag()}}
 <p>
  Please enter your OpenID, or select one of the providers below:<br>
  {{form.openid(size=80)}}
  {% for error in form.errors.openid %}
  <span style="color: red;">[{{error}}]</span>
  {% endfor %}<br>
  |{% for pr in providers %}
  <a href="javascript:set_openid('{{pr.url}}', '{{pr.name}}');">{{pr.name}}</a> |
  {% endfor %}
 </p>
 <p>{{form.remember_me}} Remember Me</p>
 <p><input type="submit" value="Sign In"></p>
</form>
{% endblock %}

这次的模板添加的东西似乎有点多。一些公共账号需要提供用户名,为了解决这个我们用了点 javascript。当用户点击相关的公共账号链接时,需要用户名的公共账号会提示用户输入用户名, javascript 会把用户名处理成可用的公共账号,最后再插入到 openid 字段的文本框中。

下面这个是在登录页面点击 google 链接后显示的截图:

2016712172533772.jpg (450×300)

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
Python 학습 : 2 시간의 일일 연구가 충분합니까?Python 학습 : 2 시간의 일일 연구가 충분합니까?Apr 18, 2025 am 12:22 AM

하루에 2 시간 동안 파이썬을 배우는 것으로 충분합니까? 목표와 학습 방법에 따라 다릅니다. 1) 명확한 학습 계획을 개발, 2) 적절한 학습 자원 및 방법을 선택하고 3) 실습 연습 및 검토 및 통합 연습 및 검토 및 통합,이 기간 동안 Python의 기본 지식과 고급 기능을 점차적으로 마스터 할 수 있습니다.

웹 개발을위한 파이썬 : 주요 응용 프로그램웹 개발을위한 파이썬 : 주요 응용 프로그램Apr 18, 2025 am 12:20 AM

웹 개발에서 Python의 주요 응용 프로그램에는 Django 및 Flask 프레임 워크 사용, API 개발, 데이터 분석 및 시각화, 머신 러닝 및 AI 및 성능 최적화가 포함됩니다. 1. Django 및 Flask 프레임 워크 : Django는 복잡한 응용 분야의 빠른 개발에 적합하며 플라스크는 소형 또는 고도로 맞춤형 프로젝트에 적합합니다. 2. API 개발 : Flask 또는 DjangorestFramework를 사용하여 RESTFULAPI를 구축하십시오. 3. 데이터 분석 및 시각화 : Python을 사용하여 데이터를 처리하고 웹 인터페이스를 통해 표시합니다. 4. 머신 러닝 및 AI : 파이썬은 지능형 웹 애플리케이션을 구축하는 데 사용됩니다. 5. 성능 최적화 : 비동기 프로그래밍, 캐싱 및 코드를 통해 최적화

Python vs. C : 성능과 효율성 탐색Python vs. C : 성능과 효율성 탐색Apr 18, 2025 am 12:20 AM

Python은 개발 효율에서 C보다 낫지 만 C는 실행 성능이 높습니다. 1. Python의 간결한 구문 및 풍부한 라이브러리는 개발 효율성을 향상시킵니다. 2.C의 컴파일 유형 특성 및 하드웨어 제어는 실행 성능을 향상시킵니다. 선택할 때는 프로젝트 요구에 따라 개발 속도 및 실행 효율성을 평가해야합니다.

Python in Action : 실제 예제Python in Action : 실제 예제Apr 18, 2025 am 12:18 AM

Python의 실제 응용 프로그램에는 데이터 분석, 웹 개발, 인공 지능 및 자동화가 포함됩니다. 1) 데이터 분석에서 Python은 Pandas 및 Matplotlib를 사용하여 데이터를 처리하고 시각화합니다. 2) 웹 개발에서 Django 및 Flask 프레임 워크는 웹 응용 프로그램 생성을 단순화합니다. 3) 인공 지능 분야에서 Tensorflow와 Pytorch는 모델을 구축하고 훈련시키는 데 사용됩니다. 4) 자동화 측면에서 파이썬 스크립트는 파일 복사와 같은 작업에 사용할 수 있습니다.

Python의 주요 용도 : 포괄적 인 개요Python의 주요 용도 : 포괄적 인 개요Apr 18, 2025 am 12:18 AM

Python은 데이터 과학, 웹 개발 및 자동화 스크립팅 필드에 널리 사용됩니다. 1) 데이터 과학에서 Python은 Numpy 및 Pandas와 같은 라이브러리를 통해 데이터 처리 및 분석을 단순화합니다. 2) 웹 개발에서 Django 및 Flask 프레임 워크를 통해 개발자는 응용 프로그램을 신속하게 구축 할 수 있습니다. 3) 자동 스크립트에서 Python의 단순성과 표준 라이브러리가 이상적입니다.

파이썬의 주요 목적 : 유연성과 사용 편의성파이썬의 주요 목적 : 유연성과 사용 편의성Apr 17, 2025 am 12:14 AM

Python의 유연성은 다중 파리가 지원 및 동적 유형 시스템에 반영되며, 사용 편의성은 간단한 구문 및 풍부한 표준 라이브러리에서 나옵니다. 유연성 : 객체 지향, 기능 및 절차 프로그래밍을 지원하며 동적 유형 시스템은 개발 효율성을 향상시킵니다. 2. 사용 편의성 : 문법은 자연 언어에 가깝고 표준 라이브러리는 광범위한 기능을 다루며 개발 프로세스를 단순화합니다.

파이썬 : 다목적 프로그래밍의 힘파이썬 : 다목적 프로그래밍의 힘Apr 17, 2025 am 12:09 AM

Python은 초보자부터 고급 개발자에 이르기까지 모든 요구에 적합한 단순성과 힘에 호의적입니다. 다목적 성은 다음과 같이 반영됩니다. 1) 배우고 사용하기 쉽고 간단한 구문; 2) Numpy, Pandas 등과 같은 풍부한 라이브러리 및 프레임 워크; 3) 다양한 운영 체제에서 실행할 수있는 크로스 플랫폼 지원; 4) 작업 효율성을 향상시키기위한 스크립팅 및 자동화 작업에 적합합니다.

하루 2 시간 안에 파이썬 학습 : 실용 가이드하루 2 시간 안에 파이썬 학습 : 실용 가이드Apr 17, 2025 am 12:05 AM

예, 하루에 2 시간 후에 파이썬을 배우십시오. 1. 합리적인 학습 계획 개발, 2. 올바른 학습 자원을 선택하십시오. 3. 실습을 통해 학습 된 지식을 통합하십시오. 이 단계는 짧은 시간 안에 Python을 마스터하는 데 도움이 될 수 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.