简体   繁体   中英

Django CSRF Protection Issue

I've just started building an API with Django for the first time and I've run into an issue while trying to test an endpoint with Postman. When I send a POST request to the endpoint http://localhost:8000/arithmetic/ containing the following JSON:

{
  "expression": "1 + 2 × 3"
}

I get the following response:

<!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>


    </div>

    <div id="info">
        <h2>Help</h2>

        <p>Reason given for failure:</p>
        <pre>
    CSRF token from the &#x27;X-Csrftoken&#x27; HTTP header has incorrect length.
    </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/4.1/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>
    </div>

</body>

</html>

I am unsure how to resolve this issue so that I can test my endpoint.

Here is my code so far:

Within the arithmetic app:

views.py:

import json
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse

# Create your views here.


def parse_request(str):
    if '×' in str:
        str = str.replace('×', '*')

    if '÷' in str:
        str = str.replace('÷', '/')


def calculate(request):
    if request.method == 'POST':
        # parse the json object
        body = json.loads(request.body)

        expression = body['expression']

        return JsonResponse({
            'response': expression
        })
    else:
        return JsonResponse({
            'error': 'invalid request method'
        })

urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.calculate)
]

And my main projects urls.py looks like this:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('arithmetic/', include('arithmetic.urls'))
]

The idea is to connect this too a React frontend that I've already developed but I want to test the endpoint on its own to ensure its working before I try to connect it to the frontend.

Any help or guidance would be greatly appreciated.

The fastest way to solve this problem is by using Django's csrf_exempt function to disable CSRF protection for your view .

from django.views.decorators.csrf import csrf_exempt

urlpatterns = [path('', csrf_exempt(views.calculate))]

You can as well use the decorator on your view:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def calculate(request):
    if request.method == 'POST':
        # parse the json object
        body = json.loads(request.body)

        expression = body['expression']

        return JsonResponse({
            'response': expression
        })
    else:
        return JsonResponse({
            'error': 'invalid request method'
        })

You can also remove the middleware completely from the config file, this would disable the CSRF protection for all the endpoints. From the config file, remove this line:

django.middleware.csrf.CsrfViewMiddleware

NOTE: This is not recommended for most cases, as it leaves your API vulnerable to CSRF attacks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM