您的位置:首页 > 科技 > IT业 > 域名的正确书写格式_南京疫情最新消息今天_济宁百度推广价格_培训班

域名的正确书写格式_南京疫情最新消息今天_济宁百度推广价格_培训班

2025/1/16 21:29:17 来源:https://blog.csdn.net/weixin_45228198/article/details/144786533  浏览:    关键词:域名的正确书写格式_南京疫情最新消息今天_济宁百度推广价格_培训班
域名的正确书写格式_南京疫情最新消息今天_济宁百度推广价格_培训班

文章目录

  • 扩展模块
  • flask-wtf 的简单使用
  • 定义用户数据模型
  • 注册与登录
  • 会话保持
    • cookie方式
    • session方式
    • 基于session的登录
  • flask-login实现登录、登出
  • 代码目录

扩展模块

  • flask-sqlalchmy,连接数据库
  • flask-login,处理用户的登录,认证
  • flask-session,会话保持,默认对用户数据加密,存储在客户端浏览器的cookie中,每次请求时携带cookie来识别用户;也可以存储在服务端的文件、数据库、缓存中;
  • flask-wtf 处理表单数据,防止csrf攻击;flask-wtf文档

 

flask-wtf 的简单使用

基于flask-wtf 制作简单的注册、登录页面;

  • 注册页面
    在这里插入图片描述
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册页面</title><script src="/static/js/index.js"></script><link rel="stylesheet" href="/static/css/index.css">
</head>
<body><form method="POST" action="/reg">{{ form.csrf_token }}<br><h3>欢迎注册</h3><br>{{ form.uname.label }} {{ form.uname(size=20) }}<br>{{ form.passwd.label }}    {{ form.passwd(size=20) }}<br>{{ form.confirm_passwd.label }} {{ form.confirm_passwd(size=20)}}<br><input type="submit" value="登录">{% if form.errors %}<ul class="errors">{% for error in form.errors %}<li>{{ error }}字段验证未通过</li>{% endfor %}</ul>{% endif %}
</form>
</body>
</html>

这里的form变量是flask渲染模板时,传入的表单对象。,form.csrf_token分别在表单中、cookie中生成一个秘钥,在提交表单时,cookie中的秘钥连同表单中的秘钥一同传给后端进行验证,验证通过则为合法的请求。
登录页面实现类似;

 

  • flask后端定义表单子类、字段、验证器,app/_init_.py
# __author__ = "laufing"
import os
from flask import Flask
from .config import BaseConfigapp = Flask(__name__)
app.config.from_object(BaseConfig)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 模板地址
app.template_folder = os.path.join(BASE_DIR, "templates")
# 静态资源地址
app.static_url_path = "/static/"
app.static_folder = os.path.join(BASE_DIR, "static")# 导入表单
from flask_wtf import FlaskForm
# 导入字段
from wtforms import StringField, PasswordField, IntegerField, DateTimeField, BooleanField
from wtforms.validators import DataRequired, InputRequired # 必须输入
from wtforms.validators import EqualToclass RegForm(FlaskForm):uname = StringField("uname", validators=[InputRequired(), DataRequired()])passwd = PasswordField("passwd", validators=[DataRequired(), InputRequired()])confirm_passwd = PasswordField("confirm_passwd", validators=[EqualTo("passwd")])class LoginForm(FlaskForm):# 在服务端验证用户的输入uname = StringField("uname", validators=[DataRequired(), InputRequired()])passwd = PasswordField("passwd", validators=[DataRequired(), InputRequired()])
  • flask后端定义视图,main.py
# __author__ = "laufing"
from app import app
from flask import render_template, jsonify, request, session, redirect, url_for
from app import LoginForm, RegForm@app.route("/reg", methods=["GET", "POST"])
def register():if request.method == "GET":form = RegForm()return render_template("reg.html", form=form)  # 传入form对象渲染表单form = RegForm()  # 接收request.form 表单数据if form.validate_on_submit():# 保存用户的信息,待实现return redirect('/login')  # 重定向到 /login  GETreturn render_template("reg.html", form=form)@app.route("/login", methods=["GET", "POST"])
def login():if request.method == "GET":  # 返回登录页面return render_template("login.html", form=LoginForm())# 实例化表单对象(自动接收request.form里的数据), 接收用户的登录数据form = LoginForm()# 按添加的验证器,进行验证数据 & 是否POST请求if form.validate_on_submit():print(form.uname.data)print(form.passwd.data)return jsonify({"code": 200,"msg": "登录成功"})# 验证未通过时,显示错误信息return render_template("login.html", form=form)if __name__ == '__main__':app.run(host="localhost", port=5050, debug=True)
  • 目录结构
    在这里插入图片描述
     

定义用户数据模型

  • 数据库mysql;
  • 驱动 flask-sqlalchmy
  • 迁移flask-migrate
    • flask db init 初始化,生成迁移目录(仅一次);
    • flask db migrate -m “描述”, 创建迁移脚本;
    • flask db upgrade,应用迁移,创建数据库、表;
    • flask db downgrade,降级
    • flask db history,迁移历史
  • 文件models/user_models.py
  • 版本
    • flask==2.0.3
    • jinja2=3.1.1
    • werkzeug == 2.0.3
    • sqlalchemy==1.3
    • flask-sqlalchemy==2.4.0
    • pyjwt==2.0.0
    • email-validator==1.0.5
    • packaging==21.0
    • flask-migrate==2.6.0

在窗口app对象的_init_.py文件中,添加如下:

from flask-sqlalchemy import SQLAlchemy
from flask-migrate import Migrate# ...db = SQLAlchemy()
db.init_app(app)
migrate = Migrate(app, db)

创建models目录/ user_models.py:

from app import dbclass UserModel(db.Model):__tablename__ = "user_t"# 必须设定主键id = db.Column(db.Integer, primary_key=True, autoincrement=True)uname = db.Column(db.String(50), unique=True)passwd = db.Column(db.String(64), unique=True)def __repr__(self):return self.uname

 
命令行下完成初始化、迁移:

flask db init
flask db migrate -m '生成迁移命令'
flask db upgrade 

 

注册与登录

将注册登录的后端逻辑迁移到指定的模块,窗口routers目录及routers.py模块,仅为了便于管理路由与视图。
routers/routers.py 路由与视图函数:

# __author__ = "laufing"
# 注册路由与视图
from app import app, RegForm, LoginForm, db
from flask import request, session, render_template, send_file  # request & session 请求上下文对象
from models.user_models import UserModel
from werkzeug.security import generate_password_hash, check_password_hash@app.route("/user/reg", methods=["GET", "POST"])  # 必须从/开始
def reg():if request.method == "GET":# 实例化表单对象form_obj = RegForm()# 渲染注册页面render_template("reg.html", form_obj=form_obj)# 实例化表单,接收request.form里的数据reg_form = RegForm()if reg_form.validate_on_submit():  # 验证通过# 保存用户的注册信息user = UserModel(uname=reg_form.uname.data, password=generate_password_hash(reg_form.passwd.data))# 通过会话保存db.session.add(user)db.session.commit()# 返回登录页面login_form = LoginForm()return render_template("login.html", form_obj=login_form)# 返回错误信息return render_template("reg.html", form_obj=reg_form)@app.route("/user/login", methods=["GET", "POST"])  # 必须从/开始
def login():if request.method == "GET":# 实例化表单对象form_obj = LoginForm()# 渲染注册页面render_template("login.html", form_obj=form_obj)# 实例化表单,接收request.form里的数据login_form = LoginForm()if login_form.validate_on_submit():  # 验证通过# 验证用户的信息uname = login_form.uname.datapasswd = login_form.passwd.data# 查询用户user = UserModel.query.filter_by(uname=uname).first()if user and check_password_hash(user.password, passwd):print("登录成功:", login_form.uname.data)# 会话保持session["uname"] = user.uname# 返回首页return render_template("index.html")else:login_form.custom_error = ["用户名或者密码错误"]return render_template("login.html", form_obj=login_form)# 返回错误信息return render_template("login.html", form_obj=login_form)

 

会话保持

  • HTTP是一种无状态的协议,即每次请求都是独立的,服务器无法识别不同请求之间的关联性,无法记录与用户的会话状态;如用户登录认证后,下次请求可能还需要重新登陆认证,造成用户体验非常不好;
  • 会话保持机制则通过在客户端和服务器之间维护一个会话标识,使得服务器可以识别并保持与客户端的连接状态;
  • 会话保持的方式
    • cookie
    • session
    • token
  • cookie,登录的用户认证通过后,通过响应res对象来set_cookie(key, value, max_age=300, expires=“xxx”)设置cookie信息,并key-val形式按域隔离存储在客户端浏览器中(大小受限、不够安全),后续的请求每次携带cookie信息,服务端通过cookie识别用户已登录认证;
  • session,用户认证通过后在服务器端存储用户的信息,并生成一个session id 返回给客户端浏览器,存储在cookie中,后续请求携带cookie中的session id 来让服务端识别会话状态;flask中的session数据是通过SECRET_KEY加密后存储在客户端浏览器的cookie中,每次请求携带cookie中的session实现自动识别会话状态;
  • token,一般在前后端分离的项目中使用jwt token来会话保持;

cookie方式

  1. 设置cookie
# 在服务端返回响应时,设置cookie
res = render_template("index.html")
res.set_cookie("uid", str(user.id), max_age=3600)  # max_age 过期时间秒
return res
  1. 验证cookie
# 识别用户的登录,通过请求上下文对象request来获取
uid = request.cookies.get("uid")
if uid:# 查询用户对象user = UserModel.query.filter_by(id=uid).first()if user:# 已登录return render_template("index.html")
  1. 删除cookie
# 退出登录时,删除cookie
res = redirect(url_for("login"))
res.delete_cookie("uid")
return res
  1. flask中生成响应对象
res = Response("xxxx")
res = make_response("xxxx")
res = jsonify({})
res = redirect(xxx)
res = render_template("index.html")

session方式

  1. 设置方式
from flask import session  # 请求上下文对象# 存储
session["uid"] = user.uid
return render_template("index.html")
  1. 验证方式
uid = session.get("uid")  # flask 底层自动从request.cookies.get("session")获取加密数据,自动验证
if uid:user = UserModel.query.filter_by(id=uid).first()if user:# 已登录认证return render_template("index.html")
  1. 删除方式
del session['uid']
# 或者
session.pop("uid", None)
  1. session的配置
# flask的配置类
class BaseConfig:# 连接uriSQLALCHEMY_DATABASE_URI = "mysql+pymysql://lauf:lauf123@localhost:3306/world"# flask-sqlalchemy追踪模型对象的修改,并且发送信号,需要额外的内存SQLALCHEMY_TRACE_MODIFICATIONS = False# 日志输出,用于调试SQLALCHEMY_ECHO = TrueHOST = "localhost"PORT = 5050DEBUG = True# 加密的秘钥,如session加密SECRET_KEY = "abcxx23"# session数据存储在Cookie中的keySESSION_COOKIE_NAME = "session_lauf"#  session过期时间PERMANENT_SESSION_LIFETIME = 3600

基于session的登录


@app.route("/user/login", methods=["GET", "POST"])  # 必须从/开始
def login():if request.method == "GET":# 实例化表单对象form_obj = LoginForm()# 渲染注册页面render_template("login.html", form_obj=form_obj)# 实例化表单,接收request.form里的数据login_form = LoginForm()if login_form.validate_on_submit():  # 验证通过# 验证用户的信息uname = login_form.uname.datapasswd = login_form.passwd.data# 查询用户user = UserModel.query.filter_by(uname=uname).first()if user and check_password_hash(user.password, passwd):print("登录成功:", login_form.uname.data)# 会话保持session["uid"] = user.id# 返回首页return render_template("index.html")else:login_form.custom_error = ["用户名或者密码错误"]return render_template("login.html", form_obj=login_form)# 返回错误信息return render_template("login.html", form_obj=login_form)# 首页
@app.route("/index", methods=["GET"])
def index():# 已登录,返回首页uid = session["uid"]  # 在获取uid时,flask底层从request.cookies.get("session_lauf")获取session数据,并解码if uid:# 查询用户对象user = UserModel.query.filter_by(id=uid).first()if user:return render_template("index.html", user=user)# 未登录,返回登录页面login_form = LoginForm()return render_template("login.html", form_obj=login_form)# 退出登录
@app.route("/user/logout", methods=["GET"])
def logout():session.pop("uid", None)# 或者del session["uid"]login_form = LoginForm()return render_template("login.html", form_obj=login_form)

 

flask-login实现登录、登出

  • Flask-Login是一个Flask扩展,它处理登录、注销和长时间记住用户会话;
  • 提供对用户会话的管理;
  • 简化用户的登录、登出、登录检查;
  • 使用方式如下:
  1. 实例化LoginManager对象
# 在 app/__init__.py 中实例化LoginManager
# app = Flask(__name__)
# 会话管理
login_manager = LoginManager()
login_manager.init_app(app)  # app需要配置SECRET_KEY, 基于session实现会话保持; 同时login_manager会放置在current_app身上
login_manager.session_protection = 'strong'  # 设置会话保护模式为强模式
login_manager.login_view = "login_view"  # 若login_required验证不通过,则定向到登录视图 (不指定时,则会提示401 Unauthorized) 通过endpoint参数指定视图的名称;login_manager.login_message = "请登录"  # 需要自己在登录的模板中处理显示
# login_required验证登录失败时,会重定向到login视图,在该视图中渲染模板并传入login_message信息
#    if request.method == "GET":# 实例化表单对象
#        form_obj = LoginForm()
#        login_message = current_app.login_manager.login_message if 'next' in request.args else None
#        print("登录失败:", request.args)# 渲染注册页面
#        return render_template("login.html", form_obj=form_obj, login_message=login_message)
# 在模板中处理login_message变量即可
  1. 定义模型类混入
    models/user_models.py中修改模型类定义。
from app import db, login_manager
from flask_login import UserMixinclass UserModel(db.Model, UserMixin):  # 继承UserMixin# ...其他不变# 定义用户对象加载
@login_manager.user_loader
def loader_user(uid):return UserModel.query.get(int(uid))
  1. 视图中处理登入、登出
    routers/routers.py
# 基于flask-login的登录
from flask_login import login_user, logout_user, login_required, current_user
# login_required 保护视图,必须登录才可以访问
# current_user 是flask-login提供的一个全局变量,在login_required保护的视图中获取当前登录的用户对象
# current_user.is_authenticated(检查用户是否已认证)、is_active(检查用户是否处于活动状态)、is_anonymous 是否匿名用户# 登录认证成功,保持会话 (在以上代码中设置session的地方,替换为如下)
login_user(user_obj)# 登出, 不传参
logout_user()# 保护视图
@app.route("/index", methods=["GET"], endpoint="index")  # endpoint为视图的名称,用户url_for 逆向解析
@login_required
def index():return render_template("index.html", user=current_user)

 

代码目录

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com