day09

csrf跨站请求伪造

1.简介
	钓鱼网站:假设是一个跟银行一模一样的网址页面,用户在该页面上转账,账户的钱会减少,但是受益人却不是自己想要转账的那个人
2.模拟
	'一台计算机,2个服务端不同端口启动,钓鱼网站提交地址改为正规网址地址'
# 新建Django项目day09,app名字app01
	1.urls.py
        path('transfer/', views.transfer),
	2.views.py
    def transfer(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            target_user = request.POST.get('target_user')
            money = request.POST.get('money')
            print(f'{username}给{target_user}转了{money}')
        return render(request, 'transfer.html')
    3.创建transfer.html
        <h1>这是真正的网站</h1>
        <form action="" method="post">
            <p>username:
                <input type="text" name="username">
            </p>
            <p>target_user:
                <input type="text" name="target_user">
            </p>
            <p>money:
                <input type="text" name="money">
            </p>
            <input type="submit" >
	4.启动Django,浏览器访问http://127.0.0.1:8000/transfer/
# 创建钓鱼网站,新建Django项目day09_1,app名字app01
	1.urls.py
    path('transfer/', views.transfer),
    2.views.py
    def transfer(request):
    return render(request, 'transfer.html')
	3.创建transfer.html
        <h1>这是钓鱼的网站</h1>
        <form action="http://127.0.0.1:8000/transfer/" method="post">
            <p>username:
                <input type="text" name="username">
            </p>
            <p>target_user:
                <input type="text">
                <input type="text" name="target_user" value="jason" style="display: none">
            </p>
            <p>money:
                <input type="text" name="money">
            </p>
            <input type="submit" >
        </form>
	4. 启动Django使用端口8001,浏览器访问http://127.0.0.1:8001/transfer/
    	输入信息之后 tony给xxx转了111,点击提交按钮,
        pycharm打印的是 tony给jason转了111
        
3.预防
	csrf策略:通过在返回的页面上添加标识信息从而区分正规网站和钓鱼网站的请求

csrf校验策略

1.form表单
	修改transfer.html
    <form action="" method="post">
        {% csrf_token %}
        .....
2.Ajax
	方式1:先编写csrf模板语法,然后利用标签查找和值获取,手动添加
        <h1>这是真正的网站</h1>
        {% csrf_token %}
        <button id="d1">点我发送Ajax请求</button>
        <script>
            $('#d1').click(function () {
                $.ajax({
                    url: '',
                    type: 'post',
                    data: {'username': 'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
                    success: function (args) {
                    }
                })
            })
        </script>
	方式2:直接李洋模板语法
        <h1>这是真正的网站</h1>
        <button id="d1">点我发送Ajax请求</button>
        <script>
            $('#d1').click(function () {
                $.ajax({
                    url: '',
                    type: 'post',
                    data:{'username': 'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
                    success: function (args) {

                    }
                })
            })
        </script>
	方式3:通用方式(利用js脚本)
    1.在static静态文件目录创建csrf.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);
            }
          }
        });
	2.修改html
        <h1>这是真正的网站</h1>
        <button id="d1">点我发送Ajax请求</button>
        <sript src="/static/csrf.js"></sript>
        <script>
            $('#d1').click(function () {
                $.ajax({
                    url: '',
                    type: 'post',
                    {#data: {'username': 'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},#}
                    {#data:{'username': 'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
                    data:{'username': 'jason'},
                    success: function (args) {

                    }
                })
            })
        </script>
    

csrf相关装饰器

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

-----------------------------FBV------------------------------
from django.views.decorators.csrf import csrf_protect,csrf_exempt
"""
csrf_protect 校验csrf
csrf_exempt  不校验csrf
"""
# @csrf_protect
@csrf_exempt
def home(request):
    return HttpResponse('哈哈哈')
-----------------------------CBV-----------------------------
针对CBV不能直接在方法上添加装饰器 需要借助于专门添加装饰器的方法
# @method_decorator(csrf_protect, name='post')  # 方式2:指名道姓的添加
class MyHome(views.View):
    @method_decorator(csrf_protect)  # 方式3:影响类中所有的方法
    def dispatch(self, request, *args, **kwargs):
        super(MyHome, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return HttpResponse('Home Get view')

    # @method_decorator(csrf_protect)  # 方式1:指名道姓的添加
    def post(self, request):
        return HttpResponse('Home Post view')
针对csrf_exempt只有方式3有效 针对其他装饰器上述三种方式都有效

auth认证模块

django执行数据库迁移命令之后会产生一个auth_user表
	该表可以配合auth模块做用户相关的功能:注册 登录 修改密码 注销 ...
 	该表还是django admin后台管理默认的表
 		django admin后台管理员账号创建 
        	python manage.py createsuperuser
      
auth模块常见功能
	1.创建用户
    	from django.contrib.auth.models import User
   		User.object.create_user(username,password)
   		User.object.create_superuser(username,password,email)
	2.校验用户名和密码是否正确
    	from django.contrib import auth
    	auth.authenticate(request,username,password)
 	3.用户登录
    	auth.login(request,user_obj)
 	4.判断用户是否登录
    	request.user.is_authecticated
 	5.获取登录用户对象
    	request.user
  	6.校验用户登录装饰器
    	from django.contrib.auth.decorators import login_required
   		跳转局部配置
       		login_required(login_url='/login/')
		跳转全局配置
        	LOGIN_URL = '/login/'
 	7.校验密码是否正确
    	request.user.check_password(old_password)
 	8.修改密码
    	request.user.set_password(new_passowrd)
   		request.user.save()
	9.注销登录
    	auth.logout(request)

auth_user表切换

1.models.py
	 from django.contrib.auth.models import AbstractUser

    class Userinfo(AbstractUser):
        '''扩展auth_user表中没有的字段'''
        phone = models.BigIntegerField()
        desc = models.TextField()
2.settings.py
	 AUTH_USER_MODEL = 'app01.Userinfo'
posted @ 2023-05-09 09:10  也曾滿眼愛意丶  阅读(18)  评论(0)    收藏  举报