Django的Rest framework搭建自定义授权登录
系列文章目录
提示:阅读本章之前,请先阅读目录
文章目录
- 系列文章目录
- 一、前言
- User模型
- User的views
- User的serializers
- utils的md5加密
- 自定义认证方法
- 配置路由
- 总路由
- 分路由
- rest的配置
一、前言
之前的文章有写过通过jwt认证的文章,今天这一篇是通过自定义用户认证的;
使用场景:有些API需要用户登录成功之后,才能访问;有些无需登录就能访问
解决方法:创建两张表,一张用户表,一张token表,保存用户登录成功后生产的token;
然后需要认证的视图,前台每次请求需要在请求头中携带token,后端然后对token进行验证
缺点:每个用户登录一次就需要生成一条token记录保存在数据库里,当用户量大的时候,就会增加后台服务器压力!
User模型
class="language-python">from django.contrib.auth.hashers import make_password, check_password
from django.db import models# Create your models here.
class User(models.Model):"""用户模型类"""username = models.CharField(max_length=32,verbose_name='用户名')password = models.CharField(max_length=64,verbose_name='密码')mobile = models.CharField(max_length=11,unique=True,verbose_name='手机号')class Meta:db_table = 'user'verbose_name = "用户信息表"verbose_name_plural = verbose_namedef __str__(self):return self.usernamedef set_password(self,password):self.password = make_password(password)return Nonedef check_pwd(self,password):return check_password(self.password,password)class UserToken(models.Model):"""用户token表"""user = models.OneToOneField(User) # 与用户一对一关系token = models.CharField(max_length=64,verbose_name='token')class Meta:db_table = 'token'verbose_name = 'token表'verbose_name_plural = verbose_name
User的views
from django.shortcuts import render# Create your views here.
from rest_framework.generics import CreateAPIView, ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIViewfrom .utils import md5
from . import models
from . import serclass UserLogin(APIView):'用户登录视图类'authentication_classes = []# 登录不需要认证def post(self,request):username = request.POST.get('username').strip()pwd = request.POST.get('password').strip()if not all([username,pwd]):return Response({'info':'参数不完整','code':400})user = models.User.objects.get(username=username)user.check_pwd(pwd)# 登录成功后生成tokentoken =md5(username)models.UserToken.objects.update_or_create(user=user,defaults={'token':token})res = {'info':'success','token':token,'code':200}res['data'] = ser.UserInfoSer(user).datareturn Response(res)class UserRegister(CreateAPIView):"""用户注册视图"""authentication_classes = []# 用户注册不需要认证serializer_class = ser.CreateUserSerclass UserInfoList(ListAPIView):"""用户详情页视图"""serializer_class = ser.UserInfoSerqueryset = models.User.objects.all()
User的serializers
class="language-python">from rest_framework import serializersfrom . import modelsclass CreateUserSer(serializers.ModelSerializer):"""新增用户序列化器"""password2 = serializers.CharField(max_length=64,write_only=True)mobile = serializers.CharField(max_length=11,min_length=11,write_only=True)def validate(self, attrs):password = attrs['password']password2 = attrs['password2']if password != password2:raise serializers.ValidationError('两次密码不一致,请重新输入!')return attrsdef validate_mobile(self,value):import reif not re.match(r'1[3-9]\d{9}',value):raise serializers.ValidationError('手机号格式不正确请重新输入!')return valuedef create(self, validated_data):del validated_data['password2']user = super().create(validated_data)user.set_password(validated_data['password'])user.save()return userclass Meta:model = models.Userfields = '__all__'class UserInfoSer(serializers.ModelSerializer):"""用户详情信息序列化器"""class Meta:model = models.Userfields = ('id','username','mobile')
utils的md5加密
import hashlib
import timedef md5(user):"""md5 加密token"""ctime = str(time.time())m = hashlib.md5(bytes(user, encoding='utf-8'))m.update(bytes(ctime, encoding='utf-8'))return m.hexdigest()
自定义认证方法
class Authtication(BaseAuthentication):def authenticate(self, request):try:token = request.META.get('HTTP_AUTHORIZATION', None)except:raise exceptions.AuthenticationFailed('用户认证失败')if token is None:raise exceptions.AuthenticationFailed('未提供认证信息')token = token.split(' ')[1]token_query = models.UserToken.objects.filter(token=token)if not token_query:raise exceptions.AuthenticationFailed('无效的token')# 返回(当前登录对象,token)return token_query.first().user, token_query.first()def authenticate_header(self, request):return 'Basic realm="user"'def authenticate_failed_response(self, exc):msg = str(exc)return Response({'msg': msg}, status=status.HTTP_401_UNAUTHORIZED)
配置路由
REST_FRAMEWORK = {# 全局使用的认证类"DEFAULT_AUTHENTICATION_CLASSES": ['users.auth.Authtication', ],"UNAUTHENTICATED_USER": None,"UNAUTHENTICATED_TOKEN": None,"DEFAULT_RENDERER_CLASSES": ['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer',]
}
总路由
urlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'^users/', include('users.urls')),
]
分路由
from django.conf.urls import include, url
from django.contrib import adminfrom . import views
urlpatterns = [url(r'^register/$',views.UserRegister.as_view()),url(r'^login/$',views.UserLogin.as_view()),url(r'^list/$',views.UserInfoList.as_view()),
]
rest的配置
REST_FRAMEWORK = {# 分页器'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',# 分页'PAGE_SIZE': 10,# 返回的时间格式'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',# 返回的数据格式'DEFAULT_RENDER_CLASSES': ['rest_framework.renderers.JSONRenderer',],# 解析request.data'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser','rest_framework.parsers.MultiPartParser',],# 全局权限'DEFAULT_PERMISSION_CLASSES': ['common.auth.Authtication'],# 认证方式'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.TokenAuthentication',],# 自定义抛出异常格式'EXCEPTION_HANDLER': 'common.custom_exception_handler.custom_exception_handler'
}
相关文章:
Django的Rest framework搭建自定义授权登录
系列文章目录 提示:阅读本章之前,请先阅读目录 文章目录 系列文章目录一、前言User模型User的viewsUser的serializersutils的md5加密自定义认证方法配置路由总路由分路由rest的配置 一、前言 之前的文章有写过通过jwt认证的文章,今天这一篇是…...

01 矩阵(力扣)多源广度优先搜索 JAVA
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。 输入:mat [[0,0,0],[0,1,0],[0,0,0]] 输出:[[0,0,0],[0,1,0],[0,0,0]] 输入…...

怎么绘制简爱思维导图?用这个工具绘制很简单
怎么绘制简爱思维导图?绘制思维导图是一项非常有用的技能,有助于梳理思路、整理知识、更好地理解和记忆信息。因此,无论你是学生、教师、工程师、项目经理或者只是想要更好地组织自己的想法,学会绘制思维导图都是非常有益的。下面…...

EC200U-CN学习(三)
EC200U系列内置丰富的网络协议,集成多个工业标准接口,并支持多种驱动和软件功能(适用于Windows 7/8/8.1/10、Linux和Android等操作系统下的USB驱动),极大地拓展了其在M2M领域的应用范围,如POS、POC、ETC、共…...

【windows】连接共享打印机提示:0x0000011B
【问题现象】 添加共享打印机的时候, 提示错误:0x0000011B。 【解决方法】 按winr键,在运行输入regedit 然后在注册表中找到路径: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print 打开后,在右侧…...

基于“RWEQ+”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写
【查看原文】基于“RWEQ”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一,土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风…...

Flutter-基础Widget
Flutter页面-基础Widget 文章目录 Flutter页面-基础WidgetWidgetStateless WidgetStateful WidgetState生命周期 基础widget文本显示TextRichTextDefaultTextStyle 图片显示FlutterLogoIconImageIamge.assetImage.fileImage.networkImage.memory CircleAvatarFadeInImage 按钮R…...

【数据分析专栏之Python篇】二、Jupyer Notebook安装配置及基本使用
文章目录 前言一、Jupter Notebook是什么1.1 简介1.2 组成部分1.3 Jupyter Notebook的主要特点 二、为什么使用Jupyter Notebook?三、安装四、Jupyter Notebok配置4.1 基本配置4.2 配置开机自启与后台运行4.3 开启代码自动补全 五、两种键盘输入模式5.1 编辑模式5.2 命令模式5…...

ubuntu22.04 DNSSEC(加密DNS服务) configuration
/etx/systemd/resolved.conf是ubuntu下DNS解析服务配置文件,systemd为ubuntu下system and service配置目录 step 1——修改resolved.conf参数 管理员权限打开 /systemd/resolved.conf sudo nano /etc/systemd/resolved.conf修改如下: # This file i…...

Qt 第一讲
登录框设置 #include "zuoye.h" #include "ui_zuoye.h"Zuoye::Zuoye(QWidget *parent): QWidget(parent), ui(new Ui::Zuoye) {ui->setupUi(this);//界面this->resize(540,420); //设置尺寸this->setFixedSize(540,420);//固定尺寸this->setS…...

IDEA 使用 maven 搭建 spring mvc
1. 创建项目 1.1 创建成功之后配置 Spring MVC 1.2 勾选 Spring MVC 2.更改配置文件 2.1 更改web.xml配置 更改为 <servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping>2.2 dispat…...

Hi3536网络应用调优
目录 1. 为什么UDP接收或发送会丢包? 2. 使用 socket 接口时,如何正确工作在非阻塞模式下? 3. TOE 使能及使用注意事项 4. TOE 模式下使用 socket 接口时的注意事项 1. 为什么UDP接收或发送会丢包? 用户态应用程序在接收 UDP 数据时࿰…...

spring拦截器 与统一格式
目录 前言模拟拦截器拦截器的实现原理什么是动态代理? 什么是静态代理静态代理与动态代理的区别两种常用的动态代理方式基于接口的动态代理基于类的动态代理 JDK Proxy 与 CGlib的区别 其他 统⼀访问前缀添加统⼀异常处理统⼀数据返回格式 前言 之前博客讲述了 , 关于SpringA…...

leetcode 122. 买卖股票的最佳时机 II
2023.7.29 把整体利润拆分成每天的利润,将股票值想象成一个折线图,将所有上升的值相加即可。 代码: class Solution { public:int maxProfit(vector<int>& prices) {int ans 0;for(int i1; i<prices.size(); i){if(prices[i]-…...
代理模式:控制访问的设计模式
代理模式:控制访问的设计模式 什么是代理模式? 代理模式是一种常见的设计模式,它允许通过代理对象来控制对真实对象的访问。代理模式的主要目的是在不改变原始对象的情况下,提供额外的功能或控制访问。 为什么要使用代理模式&a…...
2020/7/30
Educational Codeforces Round 143 (Rated for Div. 2)\C_Tea_Tasting.cpp //题意:有n种茶,n个人,第i种茶有 a[i]的量,第i个人一次能喝 b[i], 第i个人从第i种茶开始往前喝,求每个人最多能喝多少茶。 //思路ÿ…...

图形编辑器开发:是否要像 Figma 一样上 wasm
大家好,我是前端西瓜哥。 wasm 拿来做 Web 端的图形编辑器貌似是不错的选择。 因为图形处理会有相当多无法利用到 WebGL GPU 加速的 CPU 密集的计算。比如对一条复杂贝塞尔曲线进行三角化,对多个图形进行复杂图形的布尔运算。 图形编辑器性能天花板 F…...

Linux学成之路(基础篇0(二十三)MySQL服务(主从MySQL服务和读写分离——补充)
目录 一、MySQL Replication概述 优点 异步复制(Asynchronous repication) 全同步复制(Fully synchronous replication) 半同步复制(Semisynchronous replication) 三、MySQL支持的复制 四、部署主从…...

spring启动流程 (6完结) springmvc启动流程
SpringMVC的启动入口在SpringServletContainerInitializer类,它是ServletContainerInitializer实现类(Servlet3.0新特性)。在实现方法中使用WebApplicationInitializer创建ApplicationContext、创建注册DispatcherServlet、初始化ApplicationContext等。 SpringMVC…...

设计模式-中介者模式在Java中使用示例-客户信息管理
场景 欲开发客户信息管理窗口界面,界面组件之间存在较为复杂的交互关系:如果删除一个客户, 要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名称也将减少一个; 如果增加一个客户信息,…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...