Подтвердить что ты не робот

Как сделать POST простой JSON с помощью Django REST Framework? Недопустимый токен CSRF или неверный

Поражаю, кто-то покажет мне, как сделать простой запрос POST, используя JSON с картой Django REST. Я не вижу никаких примеров этого в учебнике в любом месте?

Вот мой объект модели роли, который я хотел бы ПОСТ. Это будет совершенно новая роль, которую я бы хотел добавить в базу данных, но я получаю ошибку 500.

{
    "name": "Manager", 
    "description": "someone who manages"
}

Вот мой запрос на завивание в командной строке bash:

curl -X POST -H "Content-Type: application/json" -d '[
{
    "name": "Manager", 
    "description": "someone who manages"
}]'


http://localhost:8000/lakesShoreProperties/role

URL

http://localhost:8000/lakesShoreProperties/roles

Работает с запросом GET, и я могу вытащить все роли в базе данных, но я не могу создать никаких новых ролей. У меня нет разрешений. Я использую стандартный вид в views.py

class RoleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    format = None

class RoleList(generics.ListCreateAPIView): 
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        format = None

И в моем urls.py для этого приложения соответствующие сопоставления URL-адресов верны:

url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),

Сообщение об ошибке:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

Что здесь происходит и что для этого нужно? Является ли localhost кросс-сайтом? Я добавил @csrf_exempt в RoleDetail и RoleList, но он ничего не меняет. Может ли этот декоратор быть добавлен в класс или его нужно добавить к методу? Добавляя украшение @csrf_exempt, моя ошибка становится:

Request Method: POST
Request URL:    http://127.0.0.1:8000/lakeshoreProperties/roles/
Django Version: 1.5.1
Exception Type: AttributeError
Exception Value:    
'function' object has no attribute 'as_view'

Затем я отключил CSRF через все приложение, и теперь я получаю это сообщение:

{ "non_field_errors": [ "Недопустимые данные" ]}, когда мой JSON-объект, который я знаю, действителен json. Это ошибка, отличная от поля, но я застрял здесь.

Ну, получается, что мой json недействителен?

{
    "name": "admin", 
    "description": "someone who administrates"
}

против

[
    {
        "name": "admin",
        "description": "someone who administrates"
    }
]

Наличие прилагаемых скобок [] приводит к сбою запроса POST. Но используя валидатор jsonlint.com, оба моих объекта json проверяются.

Обновление: проблема заключалась в отправке POST с PostMan, а не в бэкэнд. См. qaru.site/info/130454/...

4b9b3361

Ответ 2

CSRF освобождается по умолчанию в Django REST Framework. Поэтому запрос curl POST работает нормально. Запрос запроса POSTMAN возвратил CSRF неправильно, потому что POSTMAN включил токен csrf, если он найден в Cookies. Вы можете решить эту проблему, очистив Cookies.

Ответ 3

Это из настроек REST Framework. в вашем settings.py файле, ваш REST_FRAMEWORK должен иметь следующее.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    ),
}

Это приведет к тому, что REST Framework будет использовать аутентификацию на токенах вместо аутентификации csrf. И, установив разрешение на AllowAny, вы можете аутентифицироваться только там, где хотите.

Ответ 4

Хорошо, теперь, конечно, я возвращаю то, что я сказал. CSRF работает по назначению.

Я делал запрос POST, используя chrome-плагин под названием POSTMAN. Мой запрос POST не работает с включенным CSRF.

Но запрос POST для завивки с использованием

curl -X POST -H "Content-Type: application/json" -d '
{
    "name": "Manager",
    "description": "someone who manages"
}' http://127.0.0.1:8000/lakeshoreProperties/roles/

отлично работает... Мне пришлось снять фигурные скобки, т.е. [], И убедиться, что в ролях есть слэш после "s", т.е. Роли /, а csrf enabled не вызывает никаких ошибок.

Я не уверен, какая разница между вызовами с использованием POSTMAN - с помощью curl, но POSTMAN запускается в веб-браузере, что является самой большой разницей. Тем не менее, я отключил csrf для всего класса RoleList, но один идентичный запрос работает с Curl, но с POSTMAN не работает.

Ответ 5

Чтобы обновить текущий статус и подытожить несколько ответов:

Запросы AJAX, выполненные в том же контексте, что и API, с которыми они взаимодействуют, обычно используют SessionAuthentication. Это гарантирует, что, как только пользователь войдет в систему, любые сделанные AJAX-запросы могут быть аутентифицированы с использованием той же аутентификации на основе сеанса, которая используется для остальной части веб-сайта.

Запросы AJAX, выполненные на другом сайте из API, с которыми они общаются, обычно должны использовать схему проверки подлинности, отличную от сеанса, такую ​​как TokenAuthentication.

Поэтому ответы, рекомендующие заменить SessionAuthentication на TokenAuthentication, могут решить проблему, но не обязательно полностью верны.

Чтобы защититься от этих типов атак, вам нужно сделать две вещи:

  • Убедитесь, что "безопасные" HTTP-операции, такие как GET, HEAD и OPTIONS, не могут использоваться для изменения любого состояния на стороне сервера.

  • Убедитесь, что любые "небезопасные" HTTP-операции, такие как POST, PUT, PATCH и DELETE, всегда требуют действительного токена CSRF. Если вы используете SessionAuthentication, вам нужно включить допустимые токены CSRF для любых операций POST, PUT, PATCH или DELETE.

Чтобы сделать запросы AJAX, вам нужно включить токен CSRF в HTTP-заголовок, как описано в документации Django.

Поэтому важно, чтобы csrf был включен в заголовок, например этот ответ.

Ссылка: Работа с документацией AJAX, CSRF и CORS, Django REST.

Ответ 6

Как вы сказали, ваш URL был

http://localhost:8000/lakesShoreProperties/roles

У почтальона есть некоторые проблемы с localhost. Отправка POST на 127.0.0.1:8000/your-api/endpoint вместо этого сделала трюк для меня.

Ответ 7

Вы также можете отключить CSRF для создания своего собственного промежуточного программного обеспечения:

class DisableCSRF(object):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

И включите это промежуточное программное обеспечение в файл settings.py в MIDDLEWARE_CLASSES.

Ответ 8

у старого Postman возникает проблема с токенами csrf, поскольку он не работает с кукисами.

Я предлагаю вам перейти на новую версию postman, она работает с файлами cookie, и вы снова не столкнетесь с этой проблемой.

Ответ 9

если вы установили разрешение AllowAny и столкнулись с проблемой csrf

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny'
    ]
}

тогда размещение следующего в settings.py решит проблему

REST_SESSION_LOGIN = False