Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 643|回复: 0

前后端分离,解决跨域问题及django的csrf跨站请求保护

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-2 11:23:48 | 显示全部楼层 |阅读模式

    1. 前后端分离解决跨域问题

    解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头、正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现;

    关于跨域,前端会先发送OPTIONS请求,进行预检,检查后端是否允许前端设置的相应的请求头,请求内容

     

      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);
                    // 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({
            crossDomain: false, // obviates need for sameOrigin test
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type)) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
    官方js解决csrf

    - 浏览器error: 添加了官方解决csrftoken的js代码后,报跨域错误

    Failed to load http://127.0.0.1/course/api/signup/check_username/: Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.

    Failed to load http://127.0.0.1/course/api/signup/check_username/: Request header field X-CSRFToken is not allowed by Access-Control-Allow-Headers in preflight response.

    - 后端error:

    Forbidden (CSRF cookie not set.): /course/api/signup/check_username/
    [26/Nov/2018 16:23:06] "POST /course/api/signup/check_username/ HTTP/1.1" 403 2857
    ```
    - 解决方案是在django后端豁免跨域的中间件中添加对应的header,可以解决跨域
    ```
    class AllowOriginMiddleware(MiddlewareMixin):
    """解决跨域"""

    def process_response(self, request, response):
    # 简单请求
    response['Access-Control-Allow-Origin'] = '*'
    # 复杂请求,会先发送预检请求OPTIONS
    if request.method == 'OPTIONS':
    response['Access-Control-Allow-Headers'] = 'Content-Type,X-Requested-With,X-CSRFToken'
    response['Access-Control-Allow-Methods'] = 'POST,PUT,PATCH,DELETE'
    return response
    ```

     

     

     

     

     

     

     

     

     

     

     

     

    前后端分离解决django的csrf拦截:

    方法1、简单暴力,后端注销django的csrf中间件  'django.middleware.csrf.CsrfViewMiddleware',

    方法2、不注销csrf中间件,后端通过django提供的装饰器,为特定的视图加上装饰器进行csrf的豁免  

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    FBV:
        直接在函数上方加装饰器  @csrf_exempt  即可不验证csrf
    
    CBV:
        必须导入:from django.utils.decorators import method_decorator
    
        经测试在CBV上必须在类上加且只能给dispatch方法加
        
        # 直接在类上面加
    @method_decorator(wapper_name, name='post')    #给方法post加装饰器
    @method_decorator(wapper_name, name='get')
    class AddClass(View)
    
    注:其实也可以直接给View中的dispatch方法加装饰器,这样同样可以实现给自己类下的所有方法加装饰器(自己未定义dispatch方法时)
    @method_decorator(wapper_name, name='dispatch')
    class AddClass(View)
    
    
    注:如果注销了csrf中间件,也可以通过装饰器为个别视图添加csrf保护  

     方式3:

    django中使用Ajax请求的CSRF设置

    将官方文档上的ajax设置照搬下来:

    ----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); // 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({ crossDomain: false, // obviates need for sameOrigin test beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type)) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });

     

     

     

     

     

    django前后端不分离解决csrf:

    前后端不分离解决csrf

    form表单发送:
    1. 前端模板中需要加{% csrf_token%},本质是生成一个type类型为hidden的input标签,name=csrfmiddlewaretoken value= 随机字符串
    2. form表单,post请求直接发送
    注: 如不加csrf_token标签,form的post想成功,就智能注销后端的csrf中间件了

    ajax发送:
    3. 前端模板中加{% csrf_token%},
    方式1:在ajax中的data中加 `'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val(),`

    方式2:在ajax中添加header:`headers:{“X-CSRFToken”:$("name='csrfmiddlewaretoken'").val()}`

    方式3:通过js全局设置,和上面的方式2一样本质是从cookie中获取  【此方法也是前后端分离,前端解决csrf的官方推荐方案】

    具体见博客:(https://www.cnblogs.com/sunxiuwen/p/9675448.html#_label13)

     

    ------------------------------------------------------------------------网友见解----------------------------------------------------------------

    ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践

    解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头、正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现。

    此处手札 供后人参考~

    1.第一步 服务端设置响应头

    header('Access-Control-Allow-Origin:*');  //支持全域名访问,不安全,部署后需要固定限制为客户端网址

    header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http 动作

    header('Access-Control-Allow-Headers:x-requested-with,content-type');  //响应头 请按照自己需求添加。

    2.第二部 了解IE chrome 等浏览器 对于 跨域请求并要求设置Headers自定义参数的时候的 "预请求"   就是如果遇到 跨域并设置headers的请求,所有请求需要两步完成!

    A 第一步:发送预请求 OPTIONS 请求。此时 服务器端需要对于OPTIONS请求作出响应 一般使用202响应即可 不用返回任何内容信息。(能看到这份手稿的人,本人不相信你后台处理不了一个options请求)

    B 第二步:服务器accepted 第一步请求后 浏览器自动执行第二步 发送真正的请求。此时 大多数人 会发现请求成功了,但是 有那么几个人会发现 请求成功了但是没有任何信息返回 why?因为你自定义的请求头在服务器响应中不存在!

    查看console输出 会发现一个问题:

    “Access-Control-Allow-Headers 列表中不存在请求标头 XXXXXX”【IE】,

    request header field xxxxxx is not allowed by Access-Control-Allow-Header【chrome】

    这是因为 你的XXXX请求头 没有在服务器端被允许哦~

    遇到这个问题 只有通过修改服务器端来完成,举例:需要设置 requesttype这么一个自定义头,那么 你需要在 服务端里面 将header('Access-Control-Allow-Headers:x-requested-with,content-type,requesttype');  同学们自行体会吧 这种语法就是根据“,”分割 自己需要设置什么头,必须要在 服务端请求的响应头里面设置好,不然客户端永远永远提交不上去!

    至此  JavaScript/ajax  跨域+ 修改httpheader 任务完美实现。前端 后端完全分离 大道自成!前后期分离迎来旷古的潮流

     次处作为见证 2016年1月25日20:21:28

    "人们都一直在抱怨 JavaScript同源策略限制了web前端的发展!然而是服务端做的不够细致!"

    部分代码参考如下:代码只是提供了思想,具体步骤还要根据以上的文字 自行揣摩实现。以上内容看不懂 说明对于web一点也不了解,需要买本书看看喽~(

    客户端代码:

     

    服务器端代码

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 22:32 , Processed in 0.061984 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表