{% raw %}
Flask 和登录验证
Flask 图标
在本教程中,您将学习如何使用 Flask 和 Python 构建登录 Web 应用程序。
建立一个 Flask 登录页面
创建此 Python 文件并将其另存为app.py
:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss!"
@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong password!')
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
在此处创建了两条路由(您可以在浏览器 URL 栏中看到的路径):
@app.route('/')
@app.route('/login', methods=['POST'])
第一个显示基于登录条件的登录屏幕或主屏幕。第二个路由在登录时验证登录变量。
我们创建目录/templates/
。 使用以下代码创建文件/templates/login.html
:
{% block body %};
{% if session['logged_in'] %};
You're logged in already!
{% else %};
<form action="/login" method="POST">
<input type="username" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<input type="submit" value="Log in">
</form>
{% endif %};
{% endblock %};
{% endraw %};
使用以下命令运行 Web 应用程序:
$ python hello.py
在您的网络浏览器中打开 http://localhost:5000/ ,然后会出现登录屏幕。 登录凭据显示在do_admin_login()
函数中。
Pythonspot.com 登录界面
使它看起来很棒
功能正常时,登录屏幕看起来像 90 年代初期的用户界面(UI)。 我们从 codepen.io 中选择了一个随机登录模板。 我们使用文件style.css
创建目录/static/
。
* {
box-sizing: border-box;
}
*:focus {
outline: none;
}
body {
font-family: Arial;
background-color: #3498DB;
padding: 50px;
}
.login {
margin: 20px auto;
width: 300px;
}
.login-screen {
background-color: #FFF;
padding: 20px;
border-radius: 5px
}
.app-title {
text-align: center;
color: #777;
}
.login-form {
text-align: center;
}
.control-group {
margin-bottom: 10px;
}
input {
text-align: center;
background-color: #ECF0F1;
border: 2px solid transparent;
border-radius: 3px;
font-size: 16px;
font-weight: 200;
padding: 10px 0;
width: 250px;
transition: border .5s;
}
input:focus {
border: 2px solid #3498DB;
box-shadow: none;
}
.btn {
border: 2px solid transparent;
background: #3498DB;
color: #ffffff;
font-size: 16px;
line-height: 25px;
padding: 10px 0;
text-decoration: none;
text-shadow: none;
border-radius: 3px;
box-shadow: none;
transition: 0.25s;
display: block;
width: 250px;
margin: 0 auto;
}
.btn:hover {
background-color: #2980B9;
}
.login-link {
font-size: 12px;
color: #444;
display: block;
margin-top: 12px;
}
将login.html
模板修改为:
<link rel="stylesheet" href="/static/style.css" type="text/css">
{% block body %};
<form action="/login" method="POST">
<div class="login">
<div class="login-screen">
<div class="app-title">
<h1>Login</h1>
</div>
<div class="login-form">
<div class="control-group">
<input type="text" class="login-field" value="" placeholder="username" name="username">
<label class="login-field-icon fui-user" for="login-name"></label></div>
<div class="control-group">
<input type="password" class="login-field" value="" placeholder="password" name="password">
<label class="login-field-icon fui-lock" for="login-pass"></label></div>
<input type="submit" value="Log in" class="btn btn-primary btn-large btn-block">
</div>
</div>
</div>
</form>
{% endblock %};
重新启动应用程序后,将出现以下屏幕:
Python Flask 登录界面
很棒,不是吗? :-)
那么注销呢?
如您所见,没有注销按钮或功能。 创建起来非常容易。 下面提出的解决方案只是众多解决方案之一。 我们创建一个新的路由/logout
,它直接指向函数logout()
。 此函数清除会话变量并返回登录屏幕。
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
完整代码:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss! <a href="/logout">Logout</a>"
@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong password!')
return home()
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
连接数据库
如果要使用多用户登录系统,则应在应用程序中添加一个数据库层。Flask 没有现成的数据库支持。 如果要数据库支持,则必须使用第三方库。 在本教程中,我们将使用 SqlAlchemy。 如果您没有安装,请执行以下操作:
$ sudo pip install Flask-SqlAlchemy
SQLAlchemy 是用于 Python 编程语言的 SQL 工具箱和对象关系映射器(ORM)。 它支持 MySQL,Microsoft SQL Server 和许多其他关系数据库管理系统。 如果您不熟悉所有这些术语,请继续阅读。
创建文件tabledef.py
:
from sqlalchemy import *
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
engine = create_engine('sqlite:///tutorial.db', echo=True)
Base = declarative_base()
########################################################################
class User(Base):
""""""
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
#----------------------------------------------------------------------
def __init__(self, username, password):
""""""
self.username = username
self.password = password
# create tables
Base.metadata.create_all(engine)
使用以下命令执行:
python tabledef.py
该文件将创建数据库结构。在目录内,您将找到一个名为tutorial.db
的文件。创建一个名为dummy.py
的文件,其中将包含以下代码:
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///tutorial.db', echo=True)
# create a Session
Session = sessionmaker(bind=engine)
session = Session()
user = User("admin","password")
session.add(user)
user = User("python","python")
session.add(user)
user = User("jumpiness","python")
session.add(user)
# commit the record the database
session.commit()
session.commit()
执行:
$ python dummy.py
这会将伪数据放入数据库中。 最后,我们更新app.py
使用 SqlAlchemy 验证登录凭据
下一步是编写验证数据库中存在的用户和密码的功能。 使用 SqlAlchemy 我们可以做到这一点(虚拟/伪代码):
@app.route('/test')
def test():
POST_USERNAME = "python"
POST_PASSWORD = "python"
Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]), User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
return "Object found"
else:
return "Object not found " + POST_USERNAME + " " + POST_PASSWORD
我们使用 SqlAlchemys Oject 关系映射(ORM)。 我们将对象映射到关系数据库表,反之亦然。 定义(用户)在tabledef.py
中给出。s.query
函数是构建查询的地方。 我们有两个条件:用户名和密码必须匹配。 如果对象存在,query.first()
返回true
,否则返回false
。 这给出了以下总代码:
from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///tutorial.db', echo=True)
app = Flask(__name__)
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello Boss! <a href="/logout">Logout</a>"
@app.route('/login', methods=['POST'])
def do_admin_login():
POST_USERNAME = str(request.form['username'])
POST_PASSWORD = str(request.form['password'])
Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]), User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
session['logged_in'] = True
else:
flash('wrong password!')
return home()
@app.route("/logout")
def logout():
session['logged_in'] = False
return home()
if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=4000)
现在,您可以使用数据库表中定义的任何用户登录。
那么安全性呢?
我们在上面演示了一个简单的登录应用程序。 但是,正确保护它是您的工作。 有很多人会尝试闯入您的应用程序。
最佳做法: