django接口跨域问题和解决

django 接口跨域问题和解决

背景

需要在一个 django 的项目中,添加一组暴露接口,使该接口可以直接接口请求而不是浏览器访问

问题现象

通过外部接口请求,比如 postman 或者 apifox 发起接口请求时,接口返回:

<!DOCTYPE html>

<html lang="en">

<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="robots" content="NONE,NOARCHIVE">
  <title>403 Forbidden</title>
  <style type="text/css">
    html * {
      padding: 0;
      margin: 0;
    }

    body * {
      padding: 10px 20px;
    }

    body * * {
      padding: 0;
    }

    body {
      font: small sans-serif;
      background: #eee;
      color: #000;
    }

    body>div {
      border-bottom: 1px solid #ddd;
    }

    h1 {
      font-weight: normal;
      margin-bottom: .4em;
    }

    h1 span {
      font-size: 60%;
      color: #666;
      font-weight: normal;
    }

    #info {
      background: #f6f6f6;
    }

    #info ul {
      margin: 0.5em 4em;
    }

    #info p,
    #summary p {
      padding-top: 10px;
    }

    #summary {
      background: #ffc;
    }

    #explanation {
      background: #eee;
      border-bottom: 0px none;
    }
  </style>
</head>

<body>
  <div id="summary">
    <h1>Forbidden <span>(403)</span></h1>
    <p>CSRF verification failed. Request aborted.</p>
    <p>You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is
      required for security reasons, to ensure that your browser is not being hijacked by third parties.</p>
    <p>If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for
      &#39;same-origin&#39; requests.</p>
  </div>
  <div id="info">
    <h2>Help</h2>
    <p>Reason given for failure:</p>
    <pre>
CSRF cookie not set.
</pre>

    <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
      <a href="
https://docs.djangoproject.com/en/2.2/ref/csrf/
">Django's
        CSRF mechanism</a> has not been used correctly. For POST forms, you need to
      ensure:
    </p>

    <ul>
      <li>Your browser is accepting cookies.</li>

      <li>The view function passes a <code>request</code> to the template's <a href="
https://docs.djangoproject.com/en/dev/topics/templates/
#django.template.backends.base.Template.render"><code>render</code></a>
        method.</li>

      <li>In the template, there is a <code>{% csrf_token
%}</code> template tag inside each POST form that
        targets an internal URL.</li>

      <li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
        <code>csrf_protect</code> on any views that use the <code>csrf_token</code>
        template tag, as well as those that accept the POST data.
      </li>

      <li>The form has a valid CSRF token. After logging in in another browser
        tab or hitting the back button after a login, you may need to reload the
        page with the form, because the token is rotated after a login.</li>
    </ul>

    <p>You're seeing the help section of this page because you have <code>DEBUG =
True</code> in your Django settings file. Change that to <code>False</code>,
      and only the initial error message will be displayed. </p>

    <p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>

问题原因

Django 应用在处理 POST 请求时遇到了 CSRF(跨站请求伪造,Cross-Site Request Forgery)验证失败的问题。具体来说,错误信息指出“CSRF cookie not set”,意味着请求中没有找到预期的 CSRF cookie,这是 Django 为了防止跨站请求伪造攻击而采取的安全措施

解决方案

Django 默认并不允许跨域请求,为了允许从 Postman 或其他外部域名发起的 POST 请求,你需要设置 CORS 策略

使用 django-cors-headers

  1. 安装

pip install django-cors-headers

注意和 django 的版本对应,不同版本的 django-cors-headers 所依赖的 django 版本不同,具体可以参考:https://pypi.org/project/django-cors-headers/3.0.0/

  1. 注册

corsheaders 添加到 INSTALLED_APPS 列表中。
添加 CORS 中间件到中间件列表中,并确保它位于其他中间件之前,以便它可以最早处理 CORS 头部。
可以全局允许所有来源,或者指定允许的来源列表。

# settings.py
INSTALLED_APPS = [
    # ...
    'corsheaders',
    # ...
]

MIDDLEWARE = [
    # CORS Headers middleware should be placed as high as possible
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    # ...
]

CORS_ORIGIN_ALLOW_ALL = True  # 这将允许所有来源的请求。在生产环境中,你可能需要更严格的控制,比如列出具体的允许来源。
# 或者,你可以指定允许的源列表:
# CORS_ALLOWED_ORIGINS = [
#     "http://localhost:3000",
#     "https://example.com",
# ]

注意的就是 cors-headers 的中间件CorsMiddleware 在注册时必须放在 django-common 中间件的前一个。

但是这种方式我最终没成功,目前原因没找到。

使用装饰器 @csrf_exempt

  1. 导入
from django.views.decorators.csrf import csrf_exempt
  1. 使用
@csrf_exempt
def notify_success(request):
    # 你可以根据需要处理请求数据,这里简化处理直接返回成功信息
    return HttpResponse('success')

@csrf_exempt
def notify_failure(request):
    # 同样,这里简化处理直接返回失败信息
    return HttpResponse("failure")

使用该方式成功,apifox 再发起请求后,请求成功,跨域问题不存在。

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue生产环境中,有两种方式可以解决跨域问题: 1. 后端配置允许跨域 (1)后端配置 后端可以通过设置响应头来允许跨域请求。例如,在Django框架中,可以在视图函数中添加以下代码: ```python response['Access-Control-Allow-Origin'] = '*' ``` 这样就可以允许所有域名的请求。 (2)Vue项目配置 在Vue项目中,可以通过配置axios和接口路径来解决跨域问题。 (1)axios配置 在main.js中,可以添加以下代码: ```javascript import axios from 'axios' axios.defaults.baseURL = 'http://localhost:8000' // 设置后端接口地址 Vue.prototype.$axios = axios ``` 这样就可以在组件中使用`this.$axios`来发送请求。 (2)接口路径配置 在发送请求时,可以使用相对路径来代替绝对路径。例如: ```javascript this.$axios.get('/api/user') ``` 这样就可以发送到`http://localhost:8000/api/user`的请求。 (3)最终结果 通过以上配置,就可以在Vue生产环境中解决跨域问题。 2. 配置Nginx 另外一种解决跨域问题的方式是通过配置Nginx。具体步骤如下: (1)nginx配置 在Nginx的配置文件中,添加以下代码: ```nginx location /api/ { proxy_pass http://localhost:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ``` 这样就可以将以`/api/`开头的请求转发到`http://localhost:8000/`。 (2)最终效果 通过以上配置,就可以在Vue生产环境中解决跨域问题

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值