2017-06-19 5 views
0

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

Antwort

0

entfernen 'rest_framework.authentication.SessionAuthentication' von Ihrem DRF DEFAULT_AUTHENTICATION_CLASSES, Verwenden Sie TokenAuth nur, wenn Sie immer noch durchsuchbare API benötigen, können Sie Chrome Plugi verwenden n .

0

Ich habe das Problem gefunden. Ich habe das Token nicht korrekt zum Header hinzugefügt.

Ich bekomme das Token und den Speicher in einem lokalen Speicher.

$http.post('http://localhost:8000/api/v1/api-token-auth/', { 
    username: username, 
    password: password 
}).then(tokenSuccessFn, tokenErrorFn); 

function tokenSuccessFn(data, status, headers, config) { 

    localStorage.setItem('myApp.token',data['data'].token); 
} 

function tokenErrorFn(data, status, headers, config) { 
    console.error('token error !!!'); 
} 

Wenn die App (Seite) beginnt, lade ich das Token aus dem lokalen Speicher in app.js:

app.run(['$http', function ($http) { 


    $http.defaults.headers.common['Authorization'] = 'Token ' + localStorage.getItem('myApp.token');   
}]); 

Dank YKH für die Hilfe.

Verwandte Themen