Я создал внутреннее приложение 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',
})