10.用户登录——什么是token、生成token、token获取用户信息免密登录、登录装饰器

2023-11-05

1.为什么需要登录认证

换句话来说,为什么需要session、cookie和token
这个认证信息需要的原因,就是比如说我们今天使用淘宝点击添加购物车,然后就需要一个请求,但是发送这个请求之前,需要验证是哪个用户所登录,所以就需要一个类似通行码的东西去标识已登录。所以就存在了这些东西是吧?

2.session、cookie和token的区别

这个session的话,首先出现了他,他存储再服务端,但是服务器压力就很大,如果出现了损坏,大家都得重新登录,所以出现了cookie。cookie是存储在客户端的,但是如果web服务器做了负载均衡,下一个操作请求到了另一个服务器session就会丢失。就是无法跨设备免密登录。然后就出现了token,token是随着登录成功一起生成保存在客户端,客户端每次访问的话都是携带者token去访问服务端,所以就更加好

3.实操

在这里插入图片描述
当我们登录成功以后,并没有一个相应的标识,做出特殊的处理。这里,我们登录成功以后,就需要一个通行证的东西,去标识我们已经登录。这里可以是session、token标识。本次,我们将使用jwt(JSON WEB TOKEN)
jwt是用于生成token
jwt官网:jwt.io
jwt使用方法:github

4.用户登录_生成Token并响应——使用jwt

2.1下载jwt

pip install pyjwt

2.2 代码展示

# forum/handler/UserHandler.py
from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from uuid import uuid4
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from random import randint
import jwt
from config import secret,email
# 登录接口
class LoginHandler(BaseHandler):
    async def post(self):
        # 记录登录信息
        print("1234")
        rs_data = {}
        # 获取表单数据
        user_form = LoginUserForm(self.request.arguments)
        # 验证是否符合form表单输入的规则
        if user_form.validate():
            try:
                # 数据库中获取
                user = await manager.get(UserModel, email=user_form.email.data, password=user_form.password.data)
                # 获取到了,登录成功
                print(user_form.email.data)
                print(user_form.password.data)
                rs_data['code'] =200
                rs_data['msg'] = '登录成功!!!'
                payload = {
                    'email': user_form.email.data
                }
                # 生成一个用户信息(加密)token,返回给前端,下一次访问时,携带用户信息回来即可
                token = jwt.encode(payload, secret, algorithm='HS256')# 参数含义:加密谁,加密的密码(盐)、加密的算法
                rs_data['token'] = token
            except Exception as e: 
                # 获取不到,登录失败
                rs_data['code'] = 401
                rs_data['msg'] = '用户名或密码错误'
        else:
            rs_data['code'] = 401
            rs_data['msg'] = '用户名不符合规范'
            for f in user_form.errors:
                print(user_form.errors)
                rs_data[f] = user_form.errors[f][0]
        self.finish(rs_data)

2.3 登录完成效果展示

在这里插入图片描述

5.用户登录_token获取用户信息

5.1概述

当我们登录完成以后,前端并没有展示出登录成功的状态。这里我们需要一个接口,获取用户登录成功的信息,获取他的登录通行证token。从token中解析是否存在数据email,如果存在则登录成功。(token是随着登录时一起产生在服务端的,存放在请求头中)

5.2代码展示

5.2.1转换用户信息

# forum/models.py
# 用于创建数据表模型
from peewee import *
from forum import database
from datetime import datetime
# 创建基类:减少重复代码
class BaseModel(Model):
    create_time = DateTimeField(default = datetime.now)
    # 创建函数,用于返回用户的信息位字典形式
    def to_json(self) -> dict:
        r = {}
        for k in self.__data__.keys():
            # 判断数据是否是create_time(时间不是字符串)
            if k == 'create_time':
                r[k] = str(getattr(self,k))
            else:
                r[k] = getattr(self,k)
        return r 

5.2.2 token获取用户信息接口实现——免密登录

# forum/handler/UserHandler.py
from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from uuid import uuid4
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from random import randint
import jwt
from config import secret,email
       
# token获取用户信息接口实现——免密登录
class GetUserHandler(BaseHandler):
    async def get(self):
        rs_data = {}
        # 获取token
        token = self.request.headers.get('token')
        # 从token值解析出email
        payload = jwt.decode(token, secret, algorithms=['HS256'])
        if payload:
            # 通过email查询数据
            email = payload.get('email')
            user = await manager.get(UserModel, email=email)
            # 判断是否存在这个用户
            if user:
                # 有数据,将用户信息返回给前端
                rs_data['code'] = 200
                rs_data['msg'] = '获取用户成功!!!'
                rs_data['user'] = user.to_json()
                # 没有数据,没有登录
            else:
                rs_data['code'] = 500
                rs_data['msg'] = 'toekn错误!!!'
        else:
            rs_data['code'] = 500
            rs_data['msg'] = '请登录后再操作!!!'
        self.finish(rs_data)

5.3 效果展示

shengc

6.装饰器验证是否登录

装饰器

# forum/wtforms.py
# 完整注册(给t_user表)增加数据之前的数据验证
from wtforms_tornado import Form
from wtforms.fields import StringField
from wtforms.fields.simple import HiddenField
from wtforms.validators import DataRequired, Length

# 对t_user的数据验证
class UserForm(Form):
    id = HiddenField()
    email = StringField('账号', validators=[DataRequired(message='请填写合法的邮箱地址'),Length(min=5, max=20, message='请输入5-20长度的邮箱')])
    nick_name = StringField('昵称', validators=[Length(min=2, max=10, message='请输入2-10长度的昵称')])
    password = StringField('密码', validators=[Length(min=2, message='请输入2以上长度的密码')])
    signature = StringField('签名')
    pic = StringField('头像')

# 对登录的数据验证
class LoginUserForm(Form):
    id = HiddenField()
    email = StringField('账号', validators=[DataRequired(message='请填写合法的邮箱地址'),Length(min=5, max=20, message='请输入5-20长度的邮箱')])
    nick_name = StringField('昵称')
    password = StringField('密码', validators=[Length(min=2, message='请输入2以上长度的密码')])
    signature = StringField('签名')
    pic = StringField('头像')

优化免密登录

# forum/handler/UserHandler.py
from uuid import uuid4
from random import randint

import jwt

from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from config import secret,email
from forum.decorators import login_required_async

# 调用wtforms做添加用户数据之前的数据表单验证
class AddUserHandler(BaseHandler):
    async def post(self):
        # 创建应该响应对象
        rs_data = {}
        # 接受请求的参数并封装到Form对象中
        user_form = UserForm(self.request.arguments)
        # 前端传递的验证码
        code = self.get_body_argument('code')
        # 后端的正确的验证码
        db_code = get_code(user_form.email.data)
        if code == db_code:
            if user_form.validate():
                # 从表单中获取email信息
                email = user_form.email.data
                try:
                    # 异步查询数据表信息
                    exist_user = await manager.get(UserModel,email = email)
                    if exist_user:
                        # 存在此用户,验证失败
                        rs_data['code'] = 500
                        rs_data['msg'] = '用户名已存在'
                except Exception as e:
                    # 验证成功
                    # 异步保存数据到数据库中
                    user_form.id.data = uuid4()
                    await manager.create(UserModel,**user_form.data)
                    rs_data['code'] = 200
                    rs_data['msg'] = '注册成功'
            else:
                # 验证失败
                rs_data['code'] = 500
                rs_data['msg'] = '注册失败'
                # 将验证失败的具体原因返回给rs_data,提示信息
                for f in user_form.errors:
                    rs_data[f] = user_form.errors[f][0]
        else:
            # 验证失败
                rs_data['code'] = 500
                rs_data['msg'] = '验证码错误'
        self.finish(rs_data)

    
# 发送邮件
class SendEmailHandler(BaseHandler):
    # 用于给定4位随机验证码
    def generate_code(self) -> int:
        return randint(1000,9999)
    # 发送邮件的接口
    def post(self):
        user_email = self.get_body_argument('email') # 获取前端form输入框中输入的邮箱
        code = self.generate_code()
        msg = f'您好,您正在使用{user_email}注册<CMS论坛项目>用户注册账号,您的验证码位{code},如果不是本人操作,请忽略'
        send_mail(email.get('uname'),email.get('pwd'),user_email,'<CMS论坛项目>用户注册',msg)
        save_code(user_email,code)

# 登录接口
class LoginHandler(BaseHandler):
    async def post(self):
        # 记录登录信息
        print("1234")
        rs_data = {}
        # 获取表单数据
        user_form = LoginUserForm(self.request.arguments)
        # 验证是否符合form表单输入的规则
        if user_form.validate():
            try:
                # 数据库中获取
                user = await manager.get(UserModel, email=user_form.email.data, password=user_form.password.data)
                # 获取到了,登录成功
                print(user_form.email.data)
                print(user_form.password.data)
                rs_data['code'] =200
                rs_data['msg'] = '登录成功!!!'
                payload = {
                    'email': user_form.email.data
                }
                # 生成一个用户信息(加密)token,返回给前端,下一次访问时,携带用户信息回来即可
                token = jwt.encode(payload, secret, algorithm='HS256')# 参数含义:加密谁,加密的密码(盐)、加密的算法
                rs_data['token'] = token
            except Exception as e: 
                # 获取不到,登录失败
                rs_data['code'] = 401
                rs_data['msg'] = '用户名或密码错误'
        else:
            rs_data['code'] = 401
            rs_data['msg'] = '用户名不符合规范'
            for f in user_form.errors:
                print(user_form.errors)
                rs_data[f] = user_form.errors[f][0]
        self.finish(rs_data)
        
# token获取用户信息接口实现——免密登录
class GetUserHandler(BaseHandler):
    @login_required_async
    async def get(self):
        rs_data = {}
        id = self._user_id
        try:
            user = await manager.get(UserModel,id=id)
            # 判断是否存在这个用户
            if user:
                # 有数据,将用户信息返回给前端
                rs_data['code'] = 200
                rs_data['msg'] = '获取用户成功!!!'
                rs_data['user'] = user.to_json()
        except Exception as e:
            rs_data['code'] = 500
            rs_data['msg'] = '请登录后再操作!!!'
        self.finish(rs_data)


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

10.用户登录——什么是token、生成token、token获取用户信息免密登录、登录装饰器 的相关文章

  • 函数名称未定义

    我有一段代码 看起来像这样 if name main main def main print hello 但是 当我尝试运行此代码时 出现错误 NameError 名称 main 未定义 我是否没有在函数 def main 的第一行定义名称
  • 按每个元素中出现的数字对字符串列表进行排序[重复]

    这个问题在这里已经有答案了 我有一个脚本 其目的是对不断下载到服务器上的空间数据集文件进行排序和处理 我的列表目前大致如下 list file t00Z wrff02 grib2 file t00Z wrff03 grib2 file t0
  • 使用ideone时如何传入命令行参数?

    我正在使用 ideone 在线解释器 http ideone com http ideone com 来测试一些 C 和 Python 程序 如何指定命令行参数而不是使用 STDIN 输入 看起来你不能 但是快速破解应该做的伎俩 stati
  • 向下滚动时如何使图像移动?

    这是我想要实现的目标的示例 https www flambette com en https www flambette com en 我尝试过更改图像的 css 属性 但效果不能满足我的需求 我尝试过以下代码 mydocument on
  • 我可以同时打开两个 Tkinter Windows 吗?

    可以同时打开2个窗口吗 import tkinter as Tk import random import math root Tk Tk canvas Tk Canvas root background image Tk PhotoIma
  • NumPy 数组与 SQLite

    我在 Python 中见过的最常见的 SQLite 接口是sqlite3 但是有什么东西可以很好地与 NumPy 数组或 rearray 配合使用吗 我的意思是 它可以识别数据类型 不需要逐行插入 并提取到 NumPy rec 数组中 有点
  • DataFrame.loc 的“索引器太多”

    我读了关于切片器的文档 http pandas pydata org pandas docs stable advanced html using slicers一百万次 但我从来没有理解过它 所以我仍在试图弄清楚如何使用loc切片Data
  • argparse 不检查位置参数

    我正在创建一个脚本 它使用 argparse 接受位置参数和可选参数 我已经阅读了 Doug 的教程和 python 文档 但找不到答案 parser argparse ArgumentParser description script t
  • 如何在 python 中使用交叉验证执行 GridSearchCV

    我正在执行超参数调整RandomForest如下使用GridSearchCV X np array df features all features y np array df gold standard labels x train x
  • 使用 Python-VLC 的 PyInstaller:无属性“media_player_new”错误

    我使用 Python VLC 创建视频播放器 并使用 PyInstaller 在 Windows 10 计算机上生成可执行文件 最初 它给了我错误 Import Error Failed to load dynlib dll libvlc
  • Pygame:有人可以帮我实现双跳吗?

    我知道已经有其他关于此问题的帖子了 但我的运动系统与我发现的有点不同 所以随后我问这个问题 我的运动系统基于一个名为的命名元组Move up left right down 然后就是这个 def update self move block
  • 增强迪基-富勒测试中的 BIC 在 Python 中到底是如何工作的?

    这个问题是关于 statsmodels tsa stattools python 库 adfuller 中的增强迪基 富勒测试实现 原则上 AIC 和 BIC 应该计算一组可用模型的信息标准 并选择最好的模型 信息损失最低的模型 但它们在增
  • 将 str.contains 映射到 pandas DataFrame

    python 初学者 我正在寻找创建字符串的字典映射以及关联的值 我有一个数据框 想要创建一个新列 如果字符串匹配 则会将该列标记为 x df pd DataFrame comp dell notebook dell notebook S3
  • 在Python中随机交错2个数组

    假设我有两个数组 a 1 2 3 4 b 5 6 7 8 9 我想将这两个数组交错为变量 c 注意 a 和 b 不一定具有相同的长度 但我不希望它们以确定性的方式交错 简而言之 仅仅压缩这两个数组是不够的 我不想要 c 1 5 2 6 3
  • 解析整数集的字符串并列出间隔

    I have 2 5 7 9 12 string 我想从中获取 2 5 7 8 9 12 列表 python中有没有内置的函数 Thanks UPD 我想 直接的答案是No 不管怎样 谢谢你的 片段 使用一个 建议者斯文 马尔纳克 s 2
  • 本地主机上的 Google App Engine GQL 查询

    我正在 Google App Engine Windows 上的 SDK 版本 1 7 0 上开发一个应用程序 我需要经常测试该应用程序 并且此测试涉及数据存储上的大量 GQL 查询 您可以在 App Engine 管理界面的浏览器中在线运
  • 如何将Python包从旧版本安装到新版本?

    我正在使用 python 3 7 最近在 Linux 中安装了 python 3 8 是否有任何 bash 命令或脚本可以获取 3 7 的所有软件包列表并在 3 8 版本中一一安装 我想避免每个包裹都手工完成 注意 我将它们安装在我的系统中
  • Django 中使用外键的抽象基类继承

    我正在尝试在 Django 支持的网站上进行模型继承 以遵守 DRY 我的目标是使用一个名为 BasicCompany 的抽象基类来为三个子类提供通用信息 Butcher Baker CandlestickMaker 它们位于各自的应用程序
  • 如何使用 keras.backend.gradients() 获取梯度值

    我试图获得 Keras 模型的输出相对于模型输入 x 而不是权重 的导数 似乎最简单的方法是使用 keras backend 中的 梯度 它返回梯度张量 https keras io backend https keras io backe
  • 将二进制数转换为包含每个二进制数的数组

    我试图将二进制值转换为每个 1 0 的列表 但我得到默认的二进制值而不是列表 我有一个字符串 我将每个字符转换为二进制 它给了我一个列表 其中每个字符都有一个字符串 现在我试图将每个字符串拆分为值为 0 1 的整数 但我什么也得不到 if

随机推荐

  • 数据结构——队列

    创建队列 塞值和拿值 当我们创建一个LinkedList的时候 就可以用来模拟队列 因为该集合里有大量操作首尾元素的方法 之后就可以在该队列里进行数据的添加和获取 但是当我们使用数组来实现时 如何创建一个队列呢 最大值怎么确定 首尾初始值怎
  • 新闻主题识别及其热点演化分析流程

    1 数据收集 收集与科技新闻相关的大量文本数据 包括新闻报道 评论 社交媒体等 2 数据预处理 对收集到的文本数据进行清洗 去重 分词 停用词过滤等处理 3 特征提取 采用TF IDF Word2Vec等技术进行文本特征提取 将文本转化为向
  • Android JNI打印logcat日志

    在 JNI 中打印日志可以使用 android log print 函数来实现 该函数是 Android NDK 提供的一个用于在本地代码中输出日志消息到 logcat 的方法 要在 JNI 中打印日志 请按照以下步骤进行操作 在你的 JN
  • verilog除法器设计

    除法器原理 和十进制除法类似 计算 27 除以 5 的过程如下所示 除法运算过程如下 1 取被除数的高几位数据 位宽和除数相同 实例中是 3bit 数据 2 将被除数高位数据与除数作比较 如果前者不小于后者 则可得到对应位的商为 1 两者做
  • 线程池的基本创建方式and执行流程!

    一 什么是线程池 1 线程池 线程池是一种线程管理的机制 它是一组线程的集合 可以用来执行多个任务 线程池维护了一个固定数量的线程集合 可以从线程池中取出一个线程来执行任务 当任务执行完毕后 线程又会返回到线程池中 等待下一个任务的到来 当
  • 大学生电赛学习之路

    可以看到全国大学生电子设计大赛的认可度是非常高的 属于A类学科竞赛 电子设计大赛的形式也是给出题目 参赛者有四天三夜的时间解决问题 题目大致可以分为 控制类 测量类 高频类以及电力电子类 该竞赛会在单数年的9月份举行 但是对于新生来说电赛确
  • apk部分手机安装失败_安装apk解析包时出现错误怎么办?小编快速帮你解决

    Android智能手机的用户都会或多或少的遇到到这样的问题 安装apk解析包时出现错误 那么遇到这样的问题该如何解决 其实导致apk程序安装失败的原因是多方面的 而这所有的错误都基本归结于一点 解析包时出现错误 因此 我们只有采取逐个排查的
  • B、M、MB、K、KB、G、GB的关系

    一 概念 1 比特Bit 位 b 表示信息的最小单位 即计算机最小的存储单位 是二进制数的一位包含的信息或2个选项中特别指定1个的需要信息量 它代表从一个二进制数组中选出一元 0或1 所提供的信息量 若此二元出现的概率相等 2 字节Byte
  • Uncaught TypeError: Cannot read property ‘Component‘ of undefined

    Cannot read property Component of undefined 1 问题描述 2 解决方案 问题描述 上一篇文章中在本地搭建了第一个React项目后 跟着react中文文档学习 封装时钟的外观代码如下 class C
  • 23、账号与权限管理

    账号与权限管理 例如 生产当中 要自己创建账号 30天与 90天账号密码 本章内容 管理员用户账号和组账号 管理目录和文件的属性 文章目录 1 组的分类 2 用户的分类 3 passwd 文件账号记录详细说明 4 charge 命令 修改账
  • 关于FLAG_ACTIVITY_MULTIPLE_TASK

    FLAG ACTIVITY MULTIPLE TASK 总结 1 使用改标记 需要自行管理Activity 2 需要与FLAG ACTIVITY NEW DOCUMENT或者FLAG ACTIVITY NEW TASK共同使用 This f
  • Error in created hook: “TypeError: Object(...) is not a function“

    最近我在请求列表的时候发现请求列表报这个错 起初我是以为我的参数没有对 传给后台的是个对象 而不是json对象 但是我记得我转换了的 后来发现是我在引入封装请求的时候写错了 代码如下 import imgList from api base
  • 华为服务器手机日志文件损坏,服务器日志文件

    服务器日志文件 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 客户端IP指的是访问者 用户设备 的IP地址 在Web应用
  • 自动驾驶通信中间件ecal源码分析—1. 什么是ecal

    前面做了一套自动驾驶通信中间件 阅读了ROS 1 0 roscpp和ecal相关源码 接下来将逐步对ecal的核心源码进行简要分析 1 什么是ecal ecal是德国大陆开源的一套自动驾驶通信中间件 The enhanced Communi
  • 获取input上传文件文件名及扩展名

    1 使用input标签的type file 上传文件 获取上传文件的文件名和扩展名 代码如下
  • 安装httpd软件包

    安装httpd软件包 root www yum repos d mount dev sr0 media mount media WARNING device write protected mounted read only root ww
  • ESP32运行microPython报错:rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee

    使用Esp32调试microPython的时候 上传代码后一直报错 附 报错原因 以及解决方法 Arduino以及idf 均会出现 如下内容 无限循环打印 rst 0xc SW CPU RESET boot 0x13 SPI FAST FL
  • 自动化测试文档整理

    自动化测试 广义上讲一切使用代码或程序来辅助或代替人工测试的行为都认为是自动化测试 自动化测试作用 提高工作效率 释放人力 可以把人从一些重复性的工作中解放出来 应用环节 主要应用在回归测试和兼容性测试 适合自动化测试产品特点 1 需求比较
  • 基于深度学习的推荐算法——推荐系统模型搭建基础及DeepCrossing原理

    本章节从推荐系统模型搭建基础和DeepCrossing原理讲解及实操两方面展开 一 推荐系统模型搭建基础 1 Keras搭建模型 keras搭建模型主要有两种模式 一种是Sequential API 另外一种是Functional API
  • 10.用户登录——什么是token、生成token、token获取用户信息免密登录、登录装饰器

    1 为什么需要登录认证 换句话来说 为什么需要session cookie和token 这个认证信息需要的原因 就是比如说我们今天使用淘宝点击添加购物车 然后就需要一个请求 但是发送这个请求之前 需要验证是哪个用户所登录 所以就需要一个类似