Django 403 запрещено при отправке Post-запросов из Angular только при входе пользователя в систему - PullRequest
0 голосов
/ 25 мая 2018

Я создал внутреннее приложение Django и в настоящее время работаю над подключением внешнего интерфейса Angular, который запрашивает данные из настроек API с помощью Django rest Framework и столкнулся с проблемой, с которой вошли мои пользователи (вback-end, их вход в систему не имеет значения) получает 403 на все пост-запросы к API.Я полагаю, что из-за защиты CSRF в Django.

Я посмотрел на поток, который решил именно эту проблему, и попытался реализовать решение из этого потока , но безуспешно.

Вышедшие пользователи могут отправлять пост-запросы на регистрацию или входить в систему просто отлично.Но когда вошедший в систему пользователь пытается это сделать, он получает 403. Отправка тех же данных во время просмотра API DRF проходит успешно, поэтому я думаю, что это связано с CSRF.Чтобы быть немного более понятным, если я вошел в систему как пользователь во внешнем интерфейсе и попытался войти в систему или зарегистрировать нового пользователя (эти части не заблокированы в процессе разработки), я получаю ответ 403.Если я вошел в систему с помощью API с возможностью просмотра и отправил тот же пост-контент, он успешно работает при попытке снова войти в систему или зарегистрировать нового пользователя.

Может ли это быть из-за пользовательского заголовка?Добавляю, что может заменить заголовок CSRF?В таком случае, как я могу его переделать, так как этот заголовок необходим, или же я получаю 415 неподдерживаемый тип носителя.

Вот служба Angular, которая предоставляет функцию, которая отправляет запрос входа в систему на сервер:

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators'
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Userlogon } from '../_models/Userlogon';
import { User } from '../_models/User';

const HttpOptions = {
  headers: new HttpHeaders({ "Content-type": "application/json" })
};

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  loginobject: any;
  private usersUrl= '/api/v1/accounts/';
  private logonUrl= '/api/v1/auth/login/';
  private logoutUrl= '/api/v1/auth/logout/';

  constructor(
    private http: HttpClient
  ) { }

  login(username: string, password: string) {
    this.loginobject=JSON.stringify({"username": username, "password": password});
    return this.http.post<any>(this.logonUrl, this.loginobject, HttpOptions)
      .pipe(map(user => {
        if (user){
          console.log("If statement satisfied");
          localStorage.setItem('currentUser', JSON.stringify(user));

        }
        return user;
      }));
  }

  logout(){
    localStorage.removeItem('currentUser');
    return this.http.get<any>(this.logoutUrl).subscribe(response => console.log(response));
  }
}

Вот модуль приложения, в котором я реализовал параметры провайдера:

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule, XSRFStrategy, CookieXSRFStrategy } from '@angular/http'

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { RegisterComponent } from './register/register.component';
import { LoginComponent } from './login/login.component';
import { AlertComponent } from './_directives/alert.component';
import { ProfileComponent } from './profile/profile.component';
import { AuthGuardService } from './_guards/auth-guard.service';
import { AlertService } from './_services/alert.service';
import { AuthService } from './_services/auth.service';
import { UserService } from './_services/User.service';

@NgModule({
  declarations: [
    AppComponent,
    RegisterComponent,
    LoginComponent,
    AlertComponent,
    ProfileComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    AppRoutingModule,
    HttpClientModule,
    HttpModule
  ],
  providers: [
    {
      provide: XSRFStrategy,
      useValue: new CookieXSRFStrategy('csrftoken', 'X-CSRFToken')
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Вот шаблон, который Django обрабатывает:

{% load static %}
{% csrf_token %}
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularWebapp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
  <app-root></app-root>
{% block javascript %}
<script type="text/javascript" src="{% static 'runtime.js' %}"></script><script type="text/javascript" src="{% static 'polyfills.js' %}"></script><script type="text/javascript" src="{% static 'styles.js' %}"></script><script type="text/javascript" src="{% static 'vendor.js' %}"></script><script type="text/javascript" src="{% static 'main.js' %}"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
{% endblock %}
</body>
</html>

И, наконец,код Джанго:

from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from rest_framework import permissions, viewsets, status
from rest_framework.views import APIView
from rest_framework.response import Response
from authentication.models import Account
from authentication.permissions import IsAccountOwner
from authentication.serializers import AccountSerializer, LoginSerializer
from getorgname import scrapeorg, idgenerator
import json

# Create your views here.

class AccountViewSet(viewsets.ModelViewSet):
    lookup_field='username'
    queryset=Account.objects.all()
    serializer_class= AccountSerializer

    def get_permissions(self):
        if self.request.method in permissions.SAFE_METHODS:
            return (permissions.AllowAny(),)

        if self.request.method == 'POST':
            return (permissions.AllowAny(),)

        return (permissions.IsAuthenticated(), IsAccountOwner(),)

    def create(self, request):
        serializer=self.serializer_class(data=request.data)

        if serializer.is_valid():
            newuser=serializer.validated_data
            Account.objects.create_user(
                username=newuser.get('username'),
                email=newuser.get('email'),
                org_name=scrapeorg(newuser.get('org_number')),
                org_number=newuser.get('org_number'),
                cid=idgenerator(),
                utype=newuser.get('utype'),
                password=newuser.get('password'),
                )
            #Account.objects.create_user(**serializer.validated_data)

            return Response(serializer.validated_data, status=status.HTTP_201_CREATED)

        return Response({
            'status': 'Bad request',
            'message': 'Account could not be created with received data',
        }, status=status.HTTP_400_BAD_REQUEST)

class LoginView(APIView):
    def post(self, request):
        #data=json.loads(request.body)
        serializer=LoginSerializer(data=request.data)
        if serializer.is_valid():
            data=serializer.validated_data
            username=data.get('username')
            password=data.get('password')

            account=authenticate(username=username, password=password)

            if account != None:
                login(request, account)

                serialized = AccountSerializer(account)

                return Response(serialized.data)

            else:
                return Response({
                    'status': 'Unauthorized',
                    'message': 'Username %s and password invalid' % username 
                }, status=status.HTTP_401_UNAUTHORIZED)
        return Response({
                'status': 'Bad request',
                'message': 'Invalid data for a login request',
            }, status=status.HTTP_400_BAD_REQUEST)

class LogoutView(APIView):
    def get_permissions(self):
        return (permissions.IsAuthenticated(), IsAccountOwner(),)
    def get(self, request):
        logout(request)
        return Response({
            'status': 'Success',
            'message': 'Successfully processed logout request',
        })
...