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获取用户信息免密登录、登录装饰器 的相关文章

随机推荐

  • 数据结构——队列

    创建队列 塞值和拿值 当我们创建一个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 这个认证信息需要的原因 就是比如说我们今天使用淘宝点击添加购物车 然后就需要一个请求 但是发送这个请求之前 需要验证是哪个用户所登录 所以就需要一个类似