Django 403 forbidden when sending Post-requests fr

2019-03-02 03:50发布

I've created a back-end Django application and am currently working on hooking up an Angular front-end that requests data from API's set up using Django rest framework and have run into the problem that my logged in users (in the back-end, them being logged in on the front-end doesn't matter) get 403 on all post-requests to the API. Which I figure is because of the CSRF protection in Django.

I have look at a thread that tackled this exact problem for this and have attempted to implement the solution from this thread with no luck.

Logged out users can send post-requests to register or log in just fine. But when a logged in user tries to it gets a 403. Sending the same data while browsing the DRF API is successful, which is why I think it's related to CSRF. To be a little more clear, if I'm logged in as a user on the front-end and try to log-in or register a new user (those parts aren't blocked off in development) I get a 403 response. If I'm logged in on the browsable API and send the exact same post-content it works with successfully attempting to log me in again, or register a new user.

Can it be because of the custom header I'm adding that may be replacing the CSRF header? In that case, how can I remake it since that header is needed or else I get a 415 unsupported media type.

Here is the Angular service that provides the function that sends a login request to the server:

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));
  }
}

Here is the app module where I've implemented the provider options:

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 { }

Here is the template that Django in processes:

{% 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>

And lastly the Django view-code:

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',
        })

0条回答
登录 后发表回答