Обнаружен анонимный пользователь при доступе к rest-api с simplejwt - PullRequest
0 голосов
/ 01 октября 2019

Я могу получить доступ и обновить токен, используя SimpleJWT. У меня есть собственный декоратор, который пытается определить тип пользователя из профиля пользователя. Код завершается сбоем, потому что он не может найти аутентифицированного пользователя.

Я неоднократно пытался получить пользователя через режим отладки в VS Code, но безуспешно.

Вот мои settings.py


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', # Add this line
    'rest_auth',                # Add this line
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount', # we will not be using this but not keeping this entry results in error while deleting user. A known issue https://github.com/Tivix/django-rest-auth/issues/412
    'crispy_forms',

    'users',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

AUTH_USER_MODEL = 'users.User'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        #'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

REST_USE_JWT = True

'''
#https://www.techiediaries.com/django-rest-framework-jwt-tutorial/
JWT_AUTH = { 
    'JWT_ALLOW_REFRESH': True,
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'custom_jwt.jwt_response_payload_handler',
  # 'JWT_PAYLOAD_HANDLER': 'custom_jwt.jwt_payload_handler',
  # 'JWT_AUTH_HEADER_PREFIX': 'Bearer',
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
}
'''

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

SITE_ID = 1

Вот модель пользователя

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.conf import settings

class User(AbstractUser):



    username = models.CharField(max_length=100,blank=True, null=True)
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name']

    def __str__(self):
        return "{}".format(self.email)

class UserProfile(models.Model):
    USER_TYPE_CHOICES = (
        (1, 'ADM'),
        (2, 'GEM'),
        (3, 'JET'),
        (4, 'CAT'),
        (5, 'SPR'),
        )
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='profile')
    title = models.CharField(max_length=5)
    dob = models.DateField()
    address = models.CharField(max_length=255)
    country = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    zip = models.CharField(max_length=5)
    photo = models.ImageField(upload_to='uploads', blank=True)
    user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES,default=1,unique=False)

Вот представление, к которому я хочу получить доступ

@method_decorator(user_is_ADM,name='dispatch')
class HelloView(APIView):

    permission_classes = (IsAuthenticated,)

    def get(self, request):
        content = {'message': 'Hello, World!'}
        return Response(content)

Вот пользовательский декоратор, который беспокоит

def user_is_ADM(fun_c):
    @wraps(fun_c)
    def wrapped(request, *args, **kwargs):


        if request.user.profile.user_type == 1: <---throws error here
            return fun_c(request, *args, **kwargs)
        else:
            raise PermissionDenied
    return wrapped

Я могу получить пару токенов доступа / обновления от simplejwt, используя http://127.0.0.1:8000/api/token/ с указанием имени пользователя и пароля. Но когда я пытаюсь получить доступ к HelloView, используя http://127.0.0.1:8000/core/hello/ (ядро - имя приложения) с маркером доступа (конечно, с Authorization: Bearer ......), декоратор появляется на картинке. Теперь этому декоратору нужен request.user, чтобы проверить, является ли пользователь «GEM» или нет. Проблема в том, что ни один пользователь не вошел в систему, следовательно, система выдает ошибку, что «Анонимный» пользователь не имеет атрибута «профиль». Даже если я войду в систему как обязательное условие, возникнет та же ошибка. Я новичок в Джанго.

Как решить? Любое альтернативное предложение?

1 Ответ

0 голосов
/ 02 октября 2019

С большим количеством борьбы (что хорошо для новичка, как я), отладки, проб и ошибок, я многому научился и решил самостоятельно. Я прибег к обширной помощи средства отладки кода VS, чтобы прийти к решению, и я бы порекомендовал всем новичкам привыкнуть к этому.

Вот решение. - Я импортировал модель UserProfile, используя

from users.models import UserProfile

, затем изменил декоратор следующим образом:

def user_is_ADM(fun_c):
    @wraps(fun_c)
    def wrapped(request, *args, **kwargs):
        # 1 = ADM
        #u = UserProfile.objects.get()
        #if(request.user and request.user.is_authenticated()): 
        if(request.user and request.user.is_authenticated) :   
            user_data = UserProfile.objects.get(user_id = request.user.id)
            u = user_data.user_type


            if  u == 1:
                return fun_c(request, *args, **kwargs)
            else:
                raise PermissionDenied
    return wrapped

Проверка

  • с именем / api/ токен / с действительным именем пользователя и паролем. Для пробного использования пользовательский тип = 'ADM'
  • получил токен доступа.
  • Затем почтальон используется для вызова API helloWorld с AccessToken (конечно, с авторизацией: «токен доступа» на предъявителя).
  • теперь в игру вступил декоратор, и, как я намеренно предоставил пользователю, имеющему, это прекрасно подтверждено.
  • наконец, я мог успешно получить сообщение "Привет, мир".

Заключение - Я видел сообщения, где пользователи пытаются получить аутентификацию с использованием промежуточного программного обеспечения. Кто-то, пожалуйста, подтвердите мой подход. Конечно, @Naveen Jain и @dirkgroten оба заслуживают похвалы, поскольку они страстно руководили мной. Верный дух Stackoverflow и братства разработчиков.

Спасибо за проявленный интерес ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...