Django-用户功能设计与实现

用户功能设计与实现

用户注册接口设计

接受用户通过post方法提交的注册信息。提交格式为json数据
检查email是否已存在与数据库表中,如果存在。返回错误状态码,不存在将用户提交的数据存入表中
整个过程是resful风格,前后端分离:必须约定好url和接口(各开发各的)

路由设置

from django.conf.urls import url,include
from django.contrib import admin
from django.http import HttpResponse,HttpRequest,JsonResponse
from django.template import loader
from django.template.backends.django import Template
from django.shortcuts import render #快捷方式


def index(request): #这就是wsgi app的函数  只不过environ,start_response这两个参数给我们封装好了只需要request就行了
    # template:Template = loader.get_template('index.html')
    # print(type(template),'!!!!!',template.origin)
    # print(template.render({},request))
    return render(request,'index.html',{
        'a':['{}*{}={}'.format(i,j,i*j) for i in range(1,10) for j in range(1,10)],
        'b':list(range(1,10)),
        'd':list(range(10,20))
    })
from user.views import reg
urlpatterns = [
    url(r'^admin/', admin.site.urls), #管理后面 正则表达式(路劲) 后面视图函数
    url(r'^index',index), #首页
    url(r'^user/', include('user.urls'))  #user目录下的子目录
]

将url/user/* 映射到user/的urls

user/urls.py

from django.conf.urls import url
from django.http import HttpResponse,HttpRequest,JsonResponse
from django.shortcuts import render #快捷方式
from user.views import reg

urlpatterns = [
    url(r'',reg)
]

user/views.py

from django.shortcuts import render
from django.http import HttpResponse,HttpRequest
# Create your views here.

def reg(request:HttpRequest):
    return HttpResponse(b'user')

在这里插入图片描述

CSRF处理

这里我用的是postman,想做实验的可以下载
在这里插入图片描述
在post提交时,需给服务器发送一个csrf_token
解决方法有两个:
1.关闭中间件里的csrf验证(不推荐)
在这里插入图片描述
2.在模板的表单里加一个{% csrf_token %},它返回浏览器端会给cookie增加csrftoken字段,如果使用ajax进行post,需要在请求header中增加X-CSRFTOKEN
在这里插入图片描述
先用get请求index,获取csrftoken的值,在post的params里加入就可以访问成功了
在这里插入图片描述
先下载simplejson的包

pip install simplejson
from django.shortcuts import render
from django.http import HttpResponse,HttpRequest
import simplejson
# Create your views here.

def reg(request:HttpRequest):
    # print(request.body)
    payload = simplejson.loads(request.body)
    print(payload)
    return HttpResponse(b'user')

postman发起请求
在这里插入图片描述

用户注册

from django.shortcuts import render
from django.http import HttpResponse,HttpRequest,HttpResponseBadRequest
import simplejson
from .models import User
# Create your views here.

def reg(request:HttpRequest):
    try:
    # print(request.body)
        payload = simplejson.loads(request.body)
        email = payload['email']
        user = User.objects.filter(email=email)
        print(user.query)
        print(user,type(user))
        return HttpResponse(b'user')
    except Exception as e:
        print(e)
        return HttpResponseBadRequest('erro')

在这里插入图片描述
数据跟数据库内的用户比对

from django.shortcuts import render
from django.http import HttpResponse,HttpRequest,HttpResponseBadRequest
import simplejson
from .models import User
# Create your views here.

def reg(request:HttpRequest):
    try:
    # print(request.body)
        payload = simplejson.loads(request.body)
        email = payload['email']
        #查询数据库比对邮箱是否唯一
        user = User.objects.filter(email=email)
        # print(user.query)
        # print(user,type(user))
        if user:
            return HttpResponseBadRequest()
        
        #没有邮箱
        name = payload['name']
        password= payload['payload']
        
        user = User()
        user.name = name
        user.email=email
        user.password = password
        

        user.save() #保存到数据库  django的model、save、update、delete会自动提交
        return HttpResponse(b'user')
    
    except Exception as e:
        print(e)
        return HttpResponseBadRequest('erro')

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
用户信息数据库加入成功

Django日志

配置

在官网文档查找logging 找到example复制到setting.py
在这里插入图片描述

模型操作

管理器对象

Django会给模型类提供一个objects对象,自己指定的话,django就不提供了
在这里插入图片描述

查询

def test(request:HttpRequest):
    qs = User.objects.all()
    print(type(qs))
    print([x for x in qs])
    print([x for x in qs])
    print(qs)
    print(qs)

    return HttpResponse()

在这里插入图片描述
查询会返回结果的集,是<class ‘django.db.models.query.QuerySet’>类型
它是惰性求值,和sqlalchemy一样
惰性求值:创建查询集不会带来任何数据库的访问,直到调用使用数据才会访问数据库
缓存:每一个查询集都包含一个缓存,接下来的查询集求值将使用缓存的结果

限制查询集

all所以默认limit 21
filter过滤 返回满足条件的
exiude排除 where not value
order_by排序,参数是字符串(order_by(‘-pk’)负号逆序)
values返回一个对象字典的列表(查询语句后加,一般用于观察数据)

返回单个值得方法

get返回满足条件的对象,没有找到抛出notexist异常,找到多个抛出multipleobjectreturned异常
count返回当前查询的总条数
first返回第一个对象
exist判断查询集中是否有数据,有返回T
last返回最后一个对象

查询表达式

查询表达式作为前面查询方法的参数
语法:属性名称__比较运算符=值
属性名和运算符之间使用双下划线

startwith,endwith开头结尾
isnull,isnotnull是否为null
contains包含,大小写敏感
exact,lt,gt,lte,gte等于,小于,大于,小于等于,大于等于
前面所的前面加i忽略大小写
in在什么范围
year,month,day,week_day,hour,minute,second日期处理

Q对象

Q对象,可以使用& ,|操作符来组成逻辑表达式,~表示not

from django.db.models import Q
def test(request:HttpRequest):
    qs = User.objects.filter(Q(id=1) |Q(id=2)).values()
    # print(type(qs))
    # print([x for x in qs])
    # print([x for x in qs])
    # print(qs)
    # print(qs)
    print(qs)

    return HttpResponse()

在这里插入图片描述
如果要混合关键字查询和Q对象,Q对象必须在关键字前面

注册接口设计完善

认证

HTTP协议是无状态协议,为了解决产生了cookies和session技术
传统的session-cookies机制,就是访问浏览器好哦偶浏览器给你一个session id,session中可以创建很多东西,服务器端保存大量的session信息

无session方案
浏览器需要一个id来表示身份还要保证客户端不可篡改信息
服务器端生成一个标识,并使用某种算法对标识签名
这方案的缺点是加密,解密需要消耗cpu计算资源,无法让浏览器自己主动检查过期的数据以清除,这技术叫JWT(JSON WEB token)

import jwt

key = '123456'

payload = {'person':'hua'}

x = jwt.encode(payload,key,'HS256')
print(x)

header,payload,sig = x.split(b'.')
print(header)
print(payload)
print(sig)

import base64

def addequ(s):
    rest = 4-len(s)%4
    return s + b'='*rest

payload = addequ(payload)
print(payload)
print(base64.urlsafe_b64decode(header))
print(base64.urlsafe_b64decode(payload))
print(base64.urlsafe_b64decode(addequ(sig)))

在这里插入图片描述
JWT就是用一个key加上数据用算法加密 得到header,数据,sig
浏览器将token发给成功登录的客户端,客户端请求上带着token,浏览器在用key计算和签名对比,一样,浏览器就认可

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看源码我们知道了JWT的全部过程 下面我们自己来实现JWT的加密过程
在这里插入图片描述
加载包,得到算法
在这里插入图片描述
得到key
在这里插入图片描述
得到signing_input
在这里插入图片描述
得到signature
在这里插入图片描述
总结:jwt生成都token为三部分:header,数据,签名
数据交换:使用私钥,密钥加密

密码

加盐,使用hash(password+salt)的结果存入数据库。随机加盐,增加了破解的难度

import bcrypt

password = b'123456'

salt = bcrypt.gensalt()
x= bcrypt.hashpw(password,salt) #相同盐
y = bcrypt.hashpw(password,salt)
print(x,y,sep='\n')

x= bcrypt.hashpw(password,bcrypt.gensalt()) #不同盐
y = bcrypt.hashpw(password,bcrypt.gensalt())
print(x,y,sep='\n')

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

重写reg

def reg(request:HttpRequest):
    try:
    # print(request.body)
        payload = simplejson.loads(request.body)
        email = payload['email']
        # print(email)

        #查询数据库比对邮箱是否唯一
        user = User.objects.filter(email=email)
        # print(user.query)
        # print(user,type(user))
        if user:
            return HttpResponseBadRequest()

        #没有邮箱

        name = payload['name']
        password= payload['password']
        password = bcrypt.hashpw(password.encode(),bcrypt.gensalt())
        # print(name,email,password)

        user = User()
        user.name = name
        user.email=email
        user.password = password


        user.save() #保存到数据库  django的model、save、update、delete会自动提交

        return JsonResponse({'token':get_token(user.id)})

    except Exception as e:
        print(e)
        return HttpResponseBadRequest('erro')

在这里插入图片描述

用户功能设计与实现

用户登录接口设计

def login(request:HttpRequest):
    # qs = User.objects.filter(Q(id=1) |Q(id=2)).values()
    # print(type(qs))
    # print([x for x in qs])
    # print([x for x in qs])
    # print(qs)
    # print(qs)
    try:
        payload = simplejson.loads(request.body)
        password = payload['password'].encode()
        email = payload['email']
        user = User.objects.get(email=email)
        #验证密码
        if bcrypt.checkpw(password,user.password.encode()):
            res = JsonResponse({
                'user':{
                    'user_id':user.id,
                    'name':user.name,
                    'email':user.email,
                },
                'token':get_token(user.id)
            })
            res.set_cookie('jwt',get_token(user.id)) #token两种一个在json里  一个了可以setcookie  自己选方案

            return res
        else:
            return HttpResponseBadRequest()
    except Exception as e:
        return HttpResponseBadRequest()

在这里插入图片描述

认证

如何获取浏览器的cookie信息?
1.使用header中的Authorization
2.自定义header:使用JWT字段发送token

class SimpleMiddleware(object):
def __init__(self,get_response):
    self.get_response = get_response

def __call__(self,request):
    #request拦截处理
    #对header的jwt信息验证
    #<class 'django.core.handlers.wsgi.WSGIRequest'>
    print(type(request),'~~~~~~~~~')
    response = self.get_response(request)
    #response拦截处理
    return response

在这里插入图片描述
使用前先注册
在这里插入图片描述

装饰器实现代码

def authenticate(viewfunc):
    def wrapper(request:HttpRequest):
        # auth = request.META.get('HTTP_JWT')
        # if not auth:
        #     return HttpResponse(status=401)
        # print((request.META['HTTP_JWT']))
        try:
            auth = request.META['HTTP_JWT']
            print('!!!!!!!!')
            payload=  jwt.decode(auth,settings.SECRET_KEY, algorithms=[settings.ALG])
            print(payload,'~~~~~~~~~')
            user = User.objects.get(pk=payload['USER_ID'])
            #timestamp
            current = datetime.datetime.now().timestamp()
            delta = current - payload['TIMESTAMP']
            if delta> AUTH_EXPIRE or delta <= 0:
                print('+++++++++++++')
                return HttpResponse(status=401)
        except:
            return HttpResponse(status=401)

        ret = viewfunc(request)
        return ret
    return wrapper

@authenticate  #auth验证用户身份,不通过返回401
def test(request):
    return HttpResponse(b'test ok')

在这里插入图片描述

jwt过期

jtw在payload中增加clamin exp。exp要求int整数的时间戳(到期时间)

import jwt
import datetime
import threading
key = '123456'
payload = {
    'person':'hua',
    'exp':int(datetime.datetime.now().timestamp()) +10
}
x = jwt.encode(payload,key,'HS256')
print(1,jwt.get_unverified_header(x))
event  = threading.Event()
try:
    while not event.wait(1):
        print(datetime.datetime.now().timestamp())
        jwt.decode(x,key,algorithms=['HS256'])
except Exception as e:
    print(e)
print(2,jwt.get_unverified_header(x))

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值