今日内容回顾(django之csrf+auth认证模块)

今日内容回顾

CSRF跨站请求伪造

CSRF简介

可以简单的理解为,攻击者盗用了你的身份,以你的名义做些非法的操作。

原理

通过一个技术手段欺骗用户的浏览器访问一个自己曾经认证过的网站并运行一些操作。

由于浏览器曾经认证过,所以被访问的网站会认为是真正用户操作而运行,

利用了Web中用户身份验证的一个漏洞。

img

预防

csrf策略,通过在返回的页面上添加独一无二的标识信息从而区分正规网站和钓鱼网站的区别。

CSRF操作

form表单中添加 {% csrf_token %}

<form action=""  method="post">
	{% csrf_token %}
</form>

ajax中

方式1
	先编写csrf模板语法,然后利用标签查找和值获取,手动添加
	1. 先编写csrf模板语法	{% csrf_token %}
	2. 然后在ajax,data内编写
	'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]'
	如下:
        {% csrf_token %}
        <button id="d1">点点点</button>

        <script>
            $('#d1').click(function (){
                $.ajax({
                    url:'',
                    type:'post',
                    data:{
                        'csrfmiddlewaretoken'
                        :$('[name="csrfmiddlewaretoken"]').val()
                    },
                    success:function (args){...}})})

	</script>

方式2
	直接利用模板语法即可
	data内部直接写入	'csrfmiddlewaretoken':'{{ csrf_token }}'
	
	
	<button id="d1">点点点</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{
                'csrfmiddlewaretoken':'{{ csrf_token }}'  # 引号不能省略
            },
            success:function (args){...}})})

方式3
	通用方式(引入js脚本)扩展性高
    直接引入
        <script src="/static/myjs.js"></script>

        <button id="d1">点点点</button>
    <script src="/static/myjs.js"></script>
    <script>
        $('#d1').click(function (){
            $.ajax({
                url:'',
                type:'post',
                data:{},
                success:function (args){}})})

# 将下列JS代码封装在JS文件中引入即可
    function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');
        
function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

CSRF相关装饰器

---------------------------FBV---------------------------------------

1.当整个网站默认都不校验csrf,但是局部视图函数需要校验,如何处理

from django.views.decorators.csrf import csrf_protect
csrf_protect 校验csrf

@csrf_protect
def func(request):
    return HttpResponse("哈哈哈")

2.当整个网站默认都校验csrf,但是局部视图函数不需要校验,如何处理
from django.views.decorators.csrf import csrf_exempt
csrf_exempt 不校验csrf

@csrf_exempt
def func(request):
    return HttpResponse("哈哈哈")
 
---------------------------CBV----------------------------------------

针对CBV不能直接在方法上添加装饰器,需要借助于专门添加装饰器的方法
	from django.utils.decorators import method_decorator
1.当整个网站默认都不校验csrf,但是局部视图函数需要校验,如何处理
	from django.views.decorators.csrf import csrf_protect
	
        
	1.2 添加在类上并写入参数那个方法需要添加,指名道姓添加
    @menthod_decorator(csrf_protect,name='post') 
    class MyHome(views.View):
        
    1.3 针对重写父类方法进行添加,影响类中所有的方法
    	@menthod_decorator(csrf_protect)
    	def dispatch(self,request,*args,**kwargs):
        	return super(MyHome,self).dispatch(request,*args,**kwargs)

        def get(self,request):
            return HttpResponse(...)
    
    1.1 在CBV内部方法上添加,指明道姓的添加
        @method_decorator(csrf_protect)
        def post(self,request):
            return HttpResponse(...)
    

2.当整个网站默认都校验csrf,但是局部视图函数不需要校验,如何处理

	from django.utils.decorators import method_decorator
	from django.views.decorators.csrf import csrf_exempt	
    	针对csrf_exempt只有重写父类方法在父类方法中的dispatch添加才有效
        class MyHome(views.View):
            
            @menthod_decorators(csrf_protect)
            def dispatch(self,request,*args,**kwargs):
                return super(MyHome,self).dispatch(request, *args, **kwargs)
 

auth认证模块

Django执行数据库迁移命令之后会产生一个auth_user表

该表可以配合auth模块做用户相关的功能:注册、登录、修改密码、注销

并且还是Django admin后台管理默认的表

Django admin 后台管理员账号创建命令:python manage.py createsuperuser

需要输入,超级管理员用户名,邮箱地址,密码。

auth模块常见功能
1. 创建用户
	from django.contrib.auth.models import User
    # 创建普通用户
    User.objects.create_user(username,password)
    # 创建超级用户
    User.objects.create_superuser(username,password,email)
    
2. 校验用户名和密码是否正确
	from django.contrib import auth
    auth.authenticate(request,username=username,password=password)
    
	def login(request):
    if request.method == 'POST':
        res1 = request.user
        print(res1)
        # 当用户登录成功之后(执行了auth.login)该方法返回的是用户对象 admin
        # 当用户没有登录成功(没有执行auth.login)该方法返回匿名用户对象AnonymousUser 
        username = request.POST.get('username')
        password = request.POST.get('password')
        from django.contrib import auth
        # 查询数据库校验, 其密码会自动加密后跟数据库比对
        res = auth.authenticate(request,username=username,password=password)
        print(res)  
        # 数据正确的情况下返回的是管理员对象,
        # 数据错误的时候返回是None
        
        if res:  
        	auth.login(request,res)  # 自动操作cookie和session
    return render(request,'login.html')
3. 用户登录
	auth.login(request,res)  # 自动操作cookie和session
4. 判断用户是否登录
	request.user.is_authecticated  # 返回结果True或False
5. 获取用户对象
	request.user
    # 当用户登录成功之后(执行了auth.login)该方法返回的是用户对象 admin
   	# 当用户没有登录成功(没有执行auth.login)该方法返回匿名用户对象AnonymousUser
    
6. 校验用户登录装饰器
	from django.contrib.auth.decorators import login_required
    	跳转局部配置,在视图函数上添加 
        login_required(login_url="跳转的地址")
        跳转全局配置,在settings.py中添加
        LOGIN_URL = "/login/"
        
7. 校验密码是否正确
	request.user.check_password(old_password)

8. 修改密码
	根据旧密码修改密码
    request.user.set_password(new_password)
    request.user.save()
    
9.注销登录
	auth.logout(request)  # 清除cookie与session

auth_user表切换

当需要使用到auth_user表方法,而auth_user没有我们还需要的字段

可以考虑继承的方式,扩展auth_user表中没有的字段

继承AbstractUser来扩展auth_user表
1. 在models.py中自己创建表并继承AbstractUser
    from django.contrib.auth.models import AbstractUser

    class Userinfo(AbstractUser)
        "扩展auth_user表中没有的字段"
        phone = models.BigYntegerField()
        desc = models.TextField()
    
2. 在settings.py中配置
	"切换auth_user配置"
	AUTH_USER_MODEL= "app01.Userinfo"

"""
前提:
	auth_user没有生成之前才可以操作

"""



基于django中间件涉及项目功能

配置文件插拔式设计

import importlib
import settings

# 定义一个函数
def aaa_all(args):
    # 循环settings.py中设置好的配置文件
    for i in settings.ABC_LIST:
        # 通过字符串右切割的方式切割出循环的每一条配置文件数据
        www,eee = i.rsplit('.',maxsplit=1)  # 等于 www='a.b.msg',eee='Msg'
        # 使用importlib.import_module将'a.b.msg'进行切割
        rrr = importlib.import_module(www) # 等价于 from a.b import msg
        # 使用反射方法,从rrr(from a.b import msg)中找下有没有字符串eee(Msg)这个对象,如果有获取其属性及方法
        ttt = getattr(rrr,eee)  # 等价于 ttt = Msg()
        # 通过类实例化一个对象
        obj = ttt()  # 这个时候的ttt就等于类
        # 通过对象点类中的方法调用
        obj.aaa(args)


settings.py文件
	ABC_LIST = [
    'a.b.msg.Msg',
    'a.b.weixin.WeiXin',
    'a.b.tt.Tt',
    'a.b.qq.Qq',]
	
a包中的文件
	__init__.py
    
  	b包中的文件
    	__init__.py
        	def aaa_all(args):
                for i in settings.ABC_LIST:
                    www,eee = i.rsplit('.',maxsplit=1)
                    rrr = importlib.import_module(www)
                    ttt = getattr(rrr,eee)
                    obj = ttt()
                    obj.aaa(args)
        msg.py
        	文件中的类
            class Msg(object):
                def __init__(self):
                    pass

                def aaa(self, args):
                    print(args)

        weixin.py
        	......
        tt.py
        	......
        qq.py
        	......
			

start.py
	from a import b

    if __name__ == '__main__':
       b.aaa_all("hahhah")


posted @ 2022-09-13 23:19  瓮小辉  阅读(34)  评论(0)    收藏  举报