csrf跨站请求与auth认证

csrf跨站请求伪造

钓鱼网站:模仿一个正规的网站,让用户在该网站上做操作,但是操作的结果会影响到用户正常的网站账户但是其实有一些猫腻
    eg;英语四六级考试需要网上先缴费,但是你会发现卡里的钱扣了但是却交道了一个莫名其妙的账户并不是真正的四六级官方账户
    
    模拟钓鱼网站案例:转账案例
        内部隐藏标签
 
思考;如何区分真假网站页面发送的请求

csrf校验策略

在调教数据的位置添加唯一标识

1.form表单csrf策略
	form表单内部添加{% csrf_token %}
2.ajax请求csrf策略
	// 方式1:自己动手取值 较为繁琐
   {#data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
   // 方式2:利用模板语法自动获取(一定要用引号引起来)
   {#data:{ 'csrfmiddlewaretoken':'{{ csrf_token }}','username':'jason'},#}
   // 方式3:直接引入一个js脚本即可(官网提供的)
 	参考:https://www.cnblogs.com/Dominic-Ji/p/9234099.html

csrf相关装饰器

整个django项目都校验csrf 但是某些个数据函数/类不想校验
整个django项目都不校验csrf 但是某个视图函数/类需要校验

FBV添加装饰器的方式(与正常函数添加装饰器一致)

FBV添加装饰器

导入模块:
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
添加装饰器:
@csrf_exempt			'这个装饰器表示整体校验,局部不校验'
def home_func(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        print(name, pwd)
    return render(request, 'home.html')


@csrf_protect		"这个装饰器表示整体不校验的情况下,局部校验"
def home_func(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        print(name, pwd)
    return render(request, 'home.html')

CBV添加装饰器的方式

注意:CBV添加装饰器的方式与正常情况不一样,需要注意
    from django.views.decorators.csrf import csrf_exempt, csrf_protect

from django import views

from django.utils.decorators import method_decorator

"""这里我们三种方法针对的都是csrf_protect整体不校验,局部生效的情况"""
@method_decorator(csrf_protect, name='post')  # 方式2针对某个功能单独生效
class Hoom(views.View):
    @method_decorator(csrf_protect)  # 方式3整个类中生效
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self, request):
        return render(request, 'home.html')

    @method_decorator(csrf_protect)  # 方式1单独针对某个功能生效
    def post(self, request):
        name = request.POST.get('name')
        print(name)
"""
注意有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
 	只有在dispatch方法添加才会生效
"""

auth认证模块

前戏:django自带一个admin路由,但是需要我们提供管理员账号和密码,如果想要使用admin后台管理,需要先创建表,然后创建管理员账号
 直接执行数据库迁移命令即可产生默认的auth_user表,该表就是admin后台管理默认的认真表
1.创建超级管理员
	python38 manage.py createsuperuser
基于auth_user表编写用户相关的各项功能
	登录、校验用户是否登录、修改密码、注销登录等

扩展auth_user表

还想使用auth模块的功能,并且又想扩展auth_user表的字段
思路1:一对一字段关联
思路2:替换auth_user表
    步骤1:模型层表写模型类继承AbstracUser
  from django.contrib.auth.model import AbstractUser
	步骤2:一定要在配置文件中声明替换关系
        AUTH_USER_MODEL = 'app01.Userinfo'	这里一定要直接写应用名字.表名,固定写法
注意:替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建)

auth认证相关模块及操作

用户注册功能

from django.contrib import auth
from app01 import models
"""
auth原表操作:
from django.contrib.auth.models import User
User.objects.create_user(username=username, password=password)
"""
def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        phone = request.POST.get('phone')
        # 校验用户名是否存在
        res = models.Userinfo.objects.filter(username=username)
        if res:
            return HttpResponse('用户名已存在')
        models.Userinfo.objects.create_user(username=username, password=password, phone=phone)
        """一定要用这个方法,密码才会加密"""
        return HttpResponse('用户注册成功')

    return render(request, 'register.html')

用户登录功能

"""
auth原表操作:

判断用户名和密码是否正确
	user_obj = auth.authenticate(request,
                       username=username,
                       password=password)  
"""

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 判断用户名和密码是否正确
        user_obj = auth.authenticate(request, username=username, password=password)
        # 自动加密到表中比对
        print(user_obj)  # 这里返回的是账户和密码所对应的用户对象
        if not user_obj:
            return HttpResponse('账号或者密码错误')
        # 如果账号密码正确,返回给用户登录的令牌
        auth.login(request, user_obj)  # 自动操作django_session表
        return HttpResponse('登录成功')
    return render(request, 'login.html')
"""
当执行上面的登录操作以后,我们可以直接通过request.user拿到当前登录的用户是谁
"""

image

判断用户是否登录

实现:在前端页面有登录用户展示登录用户,没有登录展示注册和登录两个按钮
关键字:
    request.user.is_authenticated			返回的True或者False
    request.user 					     获取登录用户对象数据
    
后端写法:
    def home(request):
    return render(request, 'home.html',locals())
html写法:
<body>
    {% if request.user.is_authenticated %}
        <h1>{{ request.user }}</h1>
    {% else %}
        <a href="">登录</a>
        <a href="">注册</a>
    {% endif %}
</body>

只有登录的用户才能查看的页面

from django.contrib.auth.decorators import login_required


@login_required(login_url='/login/')  # 括号内指定没有登录跳转的页面,局部配置
"全局配置,配置文件中 LOGIN_URL = '/我们写的登录路由/'"
def home1(request):
    return HttpResponse('只有登录的用户才能查看')
"""http://127.0.0.1:8000/login/?next=/home1/,如果没有用户登录,会直接按照
我们指定的登录页面跳转,也会记录用户刚开始想要访问的网页"""

修改密码

"""
关键用语;
	校验原密码是否正确	request.user.check_password(原密码)
	修改密码
	request.user.set_password(新密码)	request.user.save()保存
"""

@login_required(login_url='/login/')
def set_pwd(request):
    if request.method == 'POST':
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        confirm_pwd = request.POST.get('confirm_pwd')
        if not new_pwd == confirm_pwd:
            return HttpResponse('两次密码输入不一致')
        # 校验原密码是否正确
        is_right = request.user.check_password(old_pwd)
        # 返回值返回的是True或者False
        if not is_right:
            return HttpResponse('原密码不正确')
        # 如果原密码正确,修改密码
        request.user.set_password(new_pwd)
        request.user.save()  # 这里一定要写,否则是不会保存密码到表里的
    return render(request, 'set_pwd.html',locals())

退出登录

auth.logout(request)
posted @ 2022-12-25 14:25  雪语  阅读(33)  评论(0)    收藏  举报