Używam Bearer token w Django. Utworzyłem zasób, który musi zwrócić niektóre informacje, jeśli użytkownik jest zalogowany, a jeśli nie, musi zwrócić inne informacje.

To jest moja konfiguracja Django

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}

Jeśli wyślę wygasły token lub nieważny. Powinien zwrócić jakieś informacje i 200 OK. Ale wewnętrznie Django zwraca 401 Unauthorized.

Jak można uniknąć tej wewnętrznej weryfikacji i wzywać ją, kiedy chcę?

1
Jimmy A. León 16 grudzień 2019, 18:02
Utwórz własną klasę uwierzytelniania, dziedzicząc klasę JWTAuthentication. W tej klasie zgłoś Wyjątki API DRF z kodem stanu 2xx
 – 
JPG
16 grudzień 2019, 19:44

1 odpowiedź

Chcesz zezwolić każdemu użytkownikowi / żądaniu na dotarcie do punktu końcowego, niezależnie od ich uprawnień lub poziomu uwierzytelniania, a następnie sprawdzić ręcznie.

Aby to zrobić, wystarczy odpowiednio ustawić permissions_classes w widoku / zestawie widoków, aby nie otrzymali błędu 401/403.

Klasy uwierzytelniania (w ustawieniach REST_FRAMEWORK) będą nadal działały przy każdym żądaniu i ustawią obiekt request.user.

class MyApi(views.APIView):
    permission_classes=[AllowAny]  # clearer than just an empty list

    def get(self, request):
        if request.user and request.user.is_authenticated:
            return Response(data={"user": request.user.email})
        else:
            return Response(data={"user": "not logged in"})

Możesz również skonsultować się z request.user.is_anonymous. Nie musisz dokładnie sprawdzać request.user and, ponieważ użytkownik powinien być zawsze obecny. Jednak zauważyłem, że narzędzia dokumentacyjne, takie jak swagger, wydają się pomijać żądanie pipline podczas generowania dokumentów, więc czasami możesz zostać wywołany bez jednego.

Nie znam SimpleJWT, ale wzorzec jest taki sam dla wszystkich klas auth.

1) Wyprowadź nową klasę z klasy podstawowej JWTAuthenticatino 2) Zastąp dowolną metodę, której potrzebujesz 3) Ustaw ją jako domyślną klasę autoryzacji w REST_FRAMEWORK

Jeśli mimo wszystko chcesz, aby prośba przeszła, to nigdy nie chcesz podbijać 401 (ouch!). W takim przypadku po prostu zwróciłbyś None dla użytkownika i ustawił atrybut niestandardowy w żądaniu, który możesz sprawdzić później. Pamiętaj, że masz 2 przypadki: 1) zły / wygasły / etc token i 2) żaden token nie został przekazany, w takim przypadku twoja klasa nie zostanie wywołana

class MyAuth(JWTAuthentication):

    def authenticate(self, request):
        try: 
            orig = super().authenticate(request)
            if orig is None:
                 setattr(request, 'my_auth_failed', True)
            return orig
        except AuthenticationFailed as e:
             setattr(request, 'my_auth_failed, True)
             setattr(request, 'my_auth_error', e)

class MyView(APIView):
    authentication_classes = [MyAuth]
    permission_classes = [AllowAny]

Nie czuję się komfortowo, zastępując podstawową logikę uwierzytelniania w ten sposób, ale jeśli jest to konieczne, zrób to. Przynajmniej staraj się, aby był jak najbardziej ograniczony i używaj go w jak najmniejszej liczbie wyświetleń.

0
Andrew 27 grudzień 2019, 06:07
Nadal zwraca 401 Nieautoryzowany, testuję wysyłanie nagłówka Authorization: Bearer null
 – 
Jimmy A. León
20 grudzień 2019, 01:47
Może to być spowodowane tym, że wartość nagłówka null jest nieprawidłowa, więc podnosi 401. Spróbuj po prostu nie wysyłać w ogóle nagłówka Authorization.
 – 
Andrew
23 grudzień 2019, 09:39
To właśnie chcę rozwiązać. Na przykład. Jeśli wyślę Bearer valid_token_but_expired, i tak chcę uzyskać informacje
 – 
Jimmy A. León
23 grudzień 2019, 20:01
Och, to ma sens. Nie wiem, jak działa prosta biblioteka JWT, stara faktycznie zwraca tekst ze szczegółami błędu. Dodam więcej szczegółów.
 – 
Andrew
24 grudzień 2019, 09:23