IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> DRF+VUE实现密码与验证码登录 -> 正文阅读

[JavaScript知识库]DRF+VUE实现密码与验证码登录

# 一、用户名+密码+jwt验证实现登录验证

下面是VUE前端登录界面部分代码

	<div class="inp" v-if="login_type==0">
	          <input v-model="username" type="text" placeholder="用户名 / 手机号码" class="user">
	          <input v-model="password" type="password" name="" class="pwd" placeholder="密码">
	          <div id="geetest1"></div>
	          <div class="rember">
	            <p>
	              <input type="checkbox" class="no" v-model="remember" name="a"/>
	              <span>记住密码</span>
	            </p>
	            <p>忘记密码</p>
	          </div>
	          <button class="login_btn" @click="loginhander">登录</button>
	          <p class="go_login">没有账号 <span>立即注册</span></p>
	        </div>
// 登录
methods: {
    loginhander() {
      if (this.username == '' || this.password == '') {
        this.$message.error("用户名或密码不能为空")
        return;
      }

      this.$axios.post("http://127.0.0.1:8000/user/authorizations/", {
        "username": this.username,
        "password": this.password
      }).then(response => {
        // 使用浏览器本地存储保存token
        if (this.remember) {
          // 记住登录
          sessionStorage.clear();
          localStorage.token = response.data.token;
          localStorage.id = response.data.id;
          localStorage.username = response.data.username;
        } else {
          // 未记住登录
          localStorage.clear();
          sessionStorage.token = response.data.token;
          sessionStorage.id = response.data.id;
          sessionStorage.username = response.data.username;
        }
        // 页面跳转回到上一个页面 也可以使用 this.$router.push("/") 回到首页
        this.$router.go(-1)

      }).catch(error => {
        this.$message.error("登录失败")
      })
    },
 }

DRF默认已经提供了认证系统Auth模块
注册一个子应用 python …/…/manage.py startapp user
在这里插入图片描述
在这里插入图片描述
在创建好的子Appuser下models.py中定义用户的用户模型类。
我们自定义的用户模型类还不能直接被Django的认证系统所识别,需要在配置文件中告知Django认证系统使用我们自定义的模型类。
在配置文件中进行设置
在这里插入图片描述在这里插入图片描述然后执行数据库迁移(必须保证是第一次迁移)
python manage.py makemigrations
python manage.py migrate

接下来安装Django REST framework JWT
在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用Json Web Token认证机制。

安装 pip install djangorestframework-jwt
settings/dev.py,进行配置
在这里插入图片描述
也可以手动生成jwt,在用户注册或登录成功后,在序列化器中返回用户信息以后同时返回token即可。

from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

接下来准备路由
在这里插入图片描述登录接口配置完成。接下来可以测试一下。
前端输入用户名和密码
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述obtain_jwt_token会进行用户名和密码的检验,验证通过则登录成功,返回token.
如果想要返回其他信息,则可以进行设置
在这里插入图片描述
修改settings/dev.py配置文件
在这里插入图片描述在这里插入图片描述然后将返回的数据根据需要存储到sessionStorage或者localStorage中

二、多条件登录(默认obtain_jwt_token只能用户名和密码登录),但是我们想实现邮箱+密码和手机号+密码登录

DRF的认证系统在收到用户名与密码时会调用authenticate()验证用户名和密码

authenticate(self, request, username=None, password=None, **kwargs)方法的参数说明:

  • request 本次认证的请求对象
  • username 本次认证提供的用户账号
  • password 本次认证提供的密码

在users/utils.py中编写:

# 增加手机或用户名或者email直接登录功能(用户名/邮箱/手机号 + 密码  )
def get_user_by_account(account):
    """
    根据帐号获取user对象
    :param account: 账号,可以是用户名username,也可以是手机号mobile, 或者其他的数据
    :return: User对象 或者 None
    """
    try:
        user = User.objects.filter(Q(username=account) | Q(mobile=account) | Q(email=account)).first()
    except User.DoesNotExist:
        return None
    else:
        return user


from .models import User
from django.db.models import Q
from django.contrib.auth.backends import ModelBackend


# 增加手机或用户名或者email直接登录功能(用户名/邮箱/手机号 + 密码  )
class UsernameMobileAuthBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        # 此时的username既可以是username,又可以是mobile
        user = get_user_by_account(username)
        # 若查找到User对象,调用User对象的check_password方法检查密码是否正确
        if user is not None and user.check_password(password) and user.is_authenticated:
            return user
        else:
            return None

在配置文件settings/dev.py中告知DRF使用我们自定义的认证后端

AUTHENTICATION_BACKENDS = [
    'user.utils.UsernameMobileAuthBackend',
]

然后就可以实现了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、邮箱+验证码登录验证

1.前端发送验证码接口准备

<div class="inp" v-show="login_type==1">
          <input v-model="email" type="text" placeholder="邮箱" class="user">
          <input v-model="code" type="text" class="pwd" placeholder="验证码">
          <button :disabled="disabled" id="get_code" @click="sendsms">{{ text }}</button>
          <button class="login_btn" @click="smsloginhander">登录</button>
          <p class="go_login">没有账号 <span>立即注册</span></p>
        </div>
//发送验证码
    sendsms() {
      //邮箱不能为空
      if (this.email == '') {
        this.$message.error("邮箱不能为空")
        return;
      }
      //校验邮箱格式是否正确
      var regEmail = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
      if (!regEmail.test(this.email)) {
        this.$message.error('邮箱格式不正确')
        return;
      }

      //禁用发送按钮
      this.disabled = true;
      //开启倒计时
      let count = 0;
      let tag = setInterval(() => {
        if (++count >= 60) {
          clearInterval(tag);
          this.disabled = false;
          this.text = "发送验证码";
          return;
        }
        this.text = `${60 - count}秒后获取`;
      }, 1000);


      //校验通过,向后端发送请求(把验证码传给后端)
      this.$axios.get("http://127.0.0.1:8000/user/captcha/", {
        //字典里面套字典传给后端
        params: {
          email: this.email,
        }
      }).then(response => {
        this.$message(response.data.message)
        // console.log(response)
      }).catch(error => {
        //后端返回的字典数据 {"message": "对不起,用户不存在!"} 会存在error.response.data中
        this.$message.error(error.response.data.message)
      })
    },

当邮箱格式都正确时,进行发送请求
在这里插入图片描述

后端封装好接口,进行数据接收和校验:
在这里插入图片描述视图函数进行校验(get请求用来给手机发送验证码,post请求用来登录验证)
在这里插入图片描述

params: {
email: this.email,
}

class CaptchaAPIView(APIView):

    def get(self, request):
        """获取验证码"""
        email = request.query_params.get("email")
        # 根据email=username查询是否有该用户
        user = get_user_by_account(email)
        if user is None:
            # 请求失败400, {"message": "对不起,用户不存在!"}字典 会返回给前端axios的catch
            return Response({"message": "对不起,用户不存在!"}, status=http_status.HTTP_400_BAD_REQUEST)

        # 邮箱存在,现在进行发送
        code = random.randrange(1000, 9999)
        print("验证码:", code)
        message = "您好!您的注册验证码是{},1分钟内有效,请勿泄露,谨防被骗。".format(code)
        # 发送短信(把code和email传过去)
        smtp_tran(message, email)

        # 验证码 写入redis(django-redis)
        conn = get_redis_connection('default')
        conn.set(email, code, ex=60)

        # 请求成功200,会返回给前端axios的catch
        return Response({"message": "发送成功!"}, status=http_status.HTTP_200_OK)

    def post(self, request):
        """验证码的验证方法"""
        # 1.获取前端传过来的数据
        user = request.data
        # user= {'email': '1293416157@qq.com', 'code': '8414'}
        # print("user=", user)

        # 2.对邮箱进行校验
        myuser = get_user_by_account(user['email'])
        if myuser is None:
            # 请求失败400, {"message": "对不起,用户不存在!"}字典 会返回给前端axios的catch
            return Response({"message": "用户邮箱不存在!"}, status=http_status.HTTP_400_BAD_REQUEST)

        # 3.校验验证码
        conn = get_redis_connection()
        redis_code = conn.get(myuser.email)  # 根据邮箱去获取验证码
        # print("redis_code=", redis_code)
        if not redis_code:
            return Response({"message": "验证码失效,请重新发送!"}, status=http_status.HTTP_400_BAD_REQUEST)
        redis_str_code = redis_code.decode('utf-8')

        if user['code'].strip() != redis_str_code:
            return Response({"message": "验证码错误!"}, status=http_status.HTTP_400_BAD_REQUEST)

        # 4.邮箱和验证码校验成功之后,返回token
        payload = jwt_payload_handler(myuser)
        token = jwt_encode_handler(payload)

        return Response({"message": "登录成功!", "username": myuser.username, "id": myuser.id, "token": token},
                        status=http_status.HTTP_200_OK)

smtp_tran(message, email)函数是发送验证码函数,可以单独建一个py文件:

import smtplib

from email.mime.text import MIMEText


def smtp_tran(message, email):
    msg = MIMEText(message, 'html', 'utf-8')
    HOST = 'smtp.qq.com'
    SUBJECT = '邮箱验证码'
    FROM = '发送的邮件@qq.com'
    TO = email   # 接收的邮件
    msg['Subject'] = SUBJECT
    msg['From'] = FROM
    msg['To'] = TO

    server = smtplib.SMTP_SSL(HOST, 465)
    server.login(FROM, '你的授权码')  # 授权码
    server.sendmail(FROM, [TO], msg.as_string())
    server.quit()

然后测试一下:前端输入框输入qq邮箱进行发送:
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

然后进行邮箱登录:http://127.0.0.1:8000/user/captcha/ 接口地址


smsloginhander() {
      //不能为空
      if (this.email == '' || this.code == '') {
        this.$message.error("邮箱或者验证码不能为空")
        return;
      }
      //校验邮箱格式是否正确
      var regEmail = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
      if (!regEmail.test(this.email)) {
        this.$message({
          message: '邮箱格式不正确',
          type: 'error'
        })
        return;
      }

      //校验通过,向后端发送请求
      this.$axios.post("http://127.0.0.1:8000/user/captcha/", {
        "email": this.email,
        "code": this.code
      }).then(response => {
        // 验证码通过以后,才发送账号和密码进行登录(当邮箱和验证码都成功后,然后再次调用jwt登录验证)
        //后端传过来的数据{"message": "登录成功!", "username": myuser.username, "id": myuser.id, "token": token}
        localStorage.clear();
        sessionStorage.clear();
        sessionStorage.token = response.data.token;
        sessionStorage.id = response.data.id;
        sessionStorage.username = response.data.username;
        // this.$message(response.data.message)
        this.$router.push("/")
      }).catch(error => {
        // console.log("error.response=", error.response)
        this.$message.error(error.response.data.message)
      })

后端接收数据进行校验:

    def post(self, request):
        """验证码的验证方法"""
        # 1.获取前端传过来的数据
        user = request.data
        # user= {'email': '1293416157@qq.com', 'code': '8414'}
        # print("user=", user)

        # 2.对邮箱进行校验
        myuser = get_user_by_account(user['email'])
        if myuser is None:
            # 请求失败400, {"message": "对不起,用户不存在!"}字典 会返回给前端axios的catch
            return Response({"message": "用户邮箱不存在!"}, status=http_status.HTTP_400_BAD_REQUEST)

        # 3.校验验证码
        conn = get_redis_connection()
        redis_code = conn.get(myuser.email)  # 根据邮箱去获取验证码
        # print("redis_code=", redis_code)
        if not redis_code:
            return Response({"message": "验证码失效,请重新发送!"}, status=http_status.HTTP_400_BAD_REQUEST)
        redis_str_code = redis_code.decode('utf-8')

        if user['code'].strip() != redis_str_code:
            return Response({"message": "验证码错误!"}, status=http_status.HTTP_400_BAD_REQUEST)

        # 4.邮箱和验证码校验成功之后,返回token(用户自定义返回jwt,之前是自动返回的)
        payload = jwt_payload_handler(myuser)   # myuser是object对象
        token = jwt_encode_handler(payload)

        return Response({"message": "登录成功!", "username": myuser.username, "id": myuser.id, "token": token},
                        status=http_status.HTTP_200_OK)

手动生成jwt

Django REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法

from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

在这里插入图片描述测试一把:
在这里插入图片描述
在这里插入图片描述
ok啦

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:30:07  更:2021-11-12 19:32:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 14:39:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码