Ich entwickle eine API mit Django REST. Der Client ist ein SPA in AngularJS, der in node.js ausgeführt wird. Registrieren und Anmeldung funktionieren, aber wenn der Benutzer tut abzumelden die Fehlermeldung gezeigt wird:Angular + Django REST Authentifizierung Anmeldeinformationen wurden nicht zur Verfügung gestellt
{ „Detail“: „Authentifizierungsinformationen wurden nicht zur Verfügung gestellt“}
ich viele Lösungen ausprobiert, wie post 1 und post 2. aber das Problem geht weiter. Wenn sich meine Angular-Dateien auf dem Server befinden, funktioniert meine Seite einwandfrei, aber wenn ich mich für ein von Yeoman erstelltes SPA ändere, habe ich das Problem mit den Anmeldedaten.
Mein settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y6u0gy4ij&[email protected]*[email protected])@)(l!-j&wmpot4h#'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'authentication',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', #
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'ServerLearn.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
WSGI_APPLICATION = 'ServerLearn.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
AUTH_USER_MODEL = 'authentication.Account'
CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/v1/.*$'
Mein models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
from django.conf import settings
# Create your models here.
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
token = Token.objects.create(user=instance)
print(token)
class AccountManager(BaseUserManager):
def create_user(self, username, password=None, **kwargs):
if not username:
raise ValueError("Need username.")
if not kwargs.get("email"):
raise ValueError("Need email.")
account = self.model(
username = username,
email = self.normalize_email(kwargs.get("email")),
name = kwargs.get("name"),
age = kwargs.get("age"),
gender = kwargs.get("gender"),
#birth = kwargs.get("birth")
)
account.set_password(password)
account.save()
return account
#admin
#senhaadmin
def create_superuser(self, username, password, **kwargs):
account = self.model(
username = username,
email = self.normalize_email(kwargs.get("email")),
name = "Admin",
age = 31111,
gender = 555,
)
account.is_admin = True
account.set_password(password)
account.save()
return account
class Account(AbstractBaseUser):
username = models.CharField(max_length = 50, unique = True)
email = models.EmailField(unique = True)
name = models.CharField(max_length = 100)
age = models.PositiveSmallIntegerField()
gender = models.PositiveSmallIntegerField()
#birth = models.DateField(null = True, blank = True)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
is_admin = models.BooleanField(default = False)
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FILES = ['username', 'email', 'name', 'age', 'gender']
def __unicode__ (self):
return self.username
Mein views.py
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():
Account.objects.create_user(**serializer.validated_data)
return Response(serializer.validated_data, status = status.HTTP_201_CREATED)
return Response({
'status': 'Bad request',
'message': 'Conta não pode ser criada'
}, status = status.HTTP_400_BAD_REQUEST)
class LoginView(views.APIView):
def post(self, request, format=None):
data = json.loads(request.body.decode('utf-8'))
username = data.get('username', None)
password = data.get('password', None)
account = authenticate(username=username, password=password)
if account is not None:
if account.is_active:
login(request, account)
serialized = AccountSerializer(account)
return Response(serialized.data)
else:
return Response({
'status': 'Unauthorized',
'message': 'This account has been disabled.'
}, status=status.HTTP_401_UNAUTHORIZED)
else:
return Response({
'status': 'Unauthorized',
'message': 'Username/password combination invalid.'
}, status=status.HTTP_401_UNAUTHORIZED)
class LogoutView(views.APIView):
#ERROR IN NEXT LINE
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, format=None):
logout(request)
return Response({}, status=status.HTTP_204_NO_CONTENT)
In meinem Angul ar Anwendung, in app.js
app.run(run);
run.$inject = ['$http'];
function run($http) {
$http.defaults.xsrfHeaderName = 'X-CSRFToken';
$http.defaults.xsrfCookieName = 'csrftoken';
}
I Token nach mit Code anmelden erhalten:
$http.post('http://localhost:8000/api/v1/api-token-auth/', {
username: username,
password: password
}).then(tokenSuccessFn, tokenErrorFn);
function tokenSuccessFn(data, status, headers, config) {
console.log("token: ");
console.log(JSON.stringify(data));
$http.defaults.headers.common.Authorization = 'Token ' + $cookies.get("csrftoken");
}
function tokenErrorFn(data, status, headers, config) {
console.error('token error !!!');
}
Die Abmelde ist
return $http.post('http://localhost:8000/api/v1/auth/logout/')
.then(logoutSuccessFn, logoutErrorFn);
function logoutSuccessFn(data, status, headers, config) {
Authentication.unauthenticate();
window.location = '/';
}
function logoutErrorFn(data, status, headers, config) {
console.error('Logout error !!!');
}