तो मेरे पास एडब्ल्यूएस कॉग्निटो टोकन की जांच के लिए नीचे यह कोड है। मैं स्पष्ट रूप से कोड की इन 6 पंक्तियों को प्रत्येक समापन बिंदु पर नहीं जोड़ना चाहता। इसके अलावा, मुझे नहीं पता कि मैं जो कुछ कर रहा हूं उसे मान्य करने का यह उचित तरीका है कि टोकन प्रारूप '' का होना चाहिए, इसे पार्स करना और जेडब्ल्यूटी टोकन भाग को डीकोड करना। मैं एडब्ल्यूएस एम्पलीफाई टोकन को कैसे प्रमाणित कर सकता हूं जो यह सुनिश्चित करने के लिए हर अनुरोध के साथ आता है कि उपयोगकर्ता ठीक से लॉग इन है। मैं इस प्रमाणीकरण को एपीआईव्यू एंडपॉइंट्स और डीआरएफ एपीआई_व्यू सजाए गए एंडपॉइंट्स में जोड़ना चाहता हूं।

View.py

import django.db.utils
from rest_framework import authentication, permissions, status
from rest_framework.views import APIView
from .serializers import *
from .models import *
from rest_framework.response import Response
from django.http import JsonResponse
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from .core.api import jwt
from django.core.exceptions import ObjectDoesNotExist
class LoginView(APIView):
    def post(self, request):
        # 'Bearer z324weroko2iorjqoi=+3r3+3ij.2o2ij4='
        token = request.META['HTTP_AUTHORIZATION'].split(' ')[1]
        print(token)
    
        # TODO this should be separated out to a login module
        try:
            res = jwt.decode_cognito_jwt(token)
            return Response(status=status.Http_200_OK)
        except:
            return Response("Invalid JWT", status=status.HTTP_401_UNAUTHORIZED)

@api_view(['GET'])
@swagger_auto_schema(
    operation_description="Get Goals joined by User"
)
def get_goals_by_user(request, user_id):
    try:
        # Get goal ids of user with id
        goals_query = JoinGoal.objects.filter(
            joiner_id=user_id).values_list('goal_id', flat=True)
        goals_list = list(goals_query)
        # Get Goals using list of goals PK with descriptions and uuid
        data = list(Goal.objects.filter(
            pk__in=goals_list).values('description', 'uuid'))
        response_data = dict(goals=data)
        return JsonResponse(response_data, status=status.HTTP_200_OK)
    except JoinGoal.DoesNotExist:
        return Response(dict(error=does_not_exist_msg(JoinGoal.__name__, 'joiner_id', user_id)), status=status.HTTP_400_BAD_REQUEST)
2
user8714896 1 सितंबर 2021, 07:22

2 जवाब

सबसे बढ़िया उत्तर

यदि djangorestframework का उपयोग कर रहे हैं, तो @bdbd का उत्तर आपके लिए सबसे अच्छा विकल्प होगा। अन्यथा, आप निम्न विकल्पों का पता लगाना चाहेंगे:

  1. अपने स्वयं के डेकोरेटर को लागू करें जो प्रमाणीकरण करेगा। इसका वही विचार है जो @login_required डेकोरेटर या @user_passes_test डेकोरेटर। कक्षा-आधारित दृश्यों के लिए ऐसे डेकोरेटर लिखते समय, शायद आपको django.utils.decorators.method_decorator
from functools import partial, wraps

from django.utils.decorators import method_decorator


def cognito_authenticator(view_func=None):
    if view_func is None:
        return partial(cognito_authenticator)

    @wraps(view_func)
    def wrapped_view(request, *args, **kwargs):
        # Check the cognito token from the request.
        token = request.META['HTTP_AUTHORIZATION'].split(' ')[1]

        try:
            res = jwt.decode_cognito_jwt(token)
            # Authenticate res if valid. Raise exception if not.
        except Exception:
            # Fail if invalid
            return HttpResponseForbidden("You are forbidden here!")
        else:
            # Proceed with the view if valid
            return view_func(request, *args, **kwargs)

    return wrapped_view


# We can decorate it here before the class definition but can also be done before the class method itself. See https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/#decorating-the-class
@method_decorator(
    name="post",
    decorator=[
        cognito_authenticator,
    ],
)
class SomeView(View):
    @method_decorator(cognito_authenticator)  # As explained above, this is another way of putting the decorator
    def get(self, request):
        return HttpResponse("Allowed entry!")

    def post(self, request):
        return HttpResponse("Allowed entry!")


# Or if using function-based views
@api_view(['POST'])
@cognito_authenticator
def some_view(request):
    return HttpResponse(f"Allowed entry!")
  1. एक कस्टम मिडलवेयर लिखें। ध्यान रखें कि आदेश मायने रखता है। डिफ़ॉल्ट AuthenticationMiddleware जो request.user फ़ील्ड को पॉप्युलेट करता है। अपने मामले में, __call__ पद्धति को लागू करें जहां आप कॉग्निटो टोकन की जांच करेंगे। जब टोकन अमान्य हो तो उस दृश्य के लिए आगे न बढ़ें, उदा। HttpResponseForbidden जैसा कि इस संदर्भ में है।
class CognitoAuthenticatorMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        token = request.META['HTTP_AUTHORIZATION'].split(' ')[1]

        try:
            res = jwt.decode_cognito_jwt(token)
            # Authenticate res if valid. Raise exception if not.
        except Exception:
            # Fail if invalid
            return HttpResponseForbidden("You are forbidden here!")

        # Proceed if valid
        response = self.get_response(request)

        return response
MIDDLEWARE = [
    ...
    'path.to.CognitoAuthenticatorMiddleware',
    ...
]

अद्यतन

यहां विकल्प -1 का उपयोग करके एक नमूना चलाया गया है। सरलता के लिए, settings.py केवल डिफ़ॉल्ट सेटिंग है।

views.py

from functools import partial, wraps

from django.http import HttpResponse, HttpResponseForbidden
from django.utils.decorators import method_decorator
from django.views import View  # If using django views
from rest_framework.views import APIView  # If using djangorestframework views


def cognito_authenticator(view_func=None):
    if view_func is None:
        return partial(cognito_authenticator)

    @wraps(view_func)
    def wrapped_view(request, *args, **kwargs):
        # To simplify the authentication, we would check if there is a query parameter "name=me". If none, it is forbidden.
        if request.GET.get('name') == "me":
            return view_func(request, *args, **kwargs)
        return HttpResponseForbidden("You are forbidden here!")

    return wrapped_view


@method_decorator(  # Try this style-1
    name="get",
    decorator=[
        cognito_authenticator,
    ],
)
class SomeView(View):  # If using djangorestframework view, this can also inherit from APIView or others e.g. class SomeView(APIView):
    @method_decorator(cognito_authenticator)  # Or try this style-2
    def get(self, request):
        return HttpResponse(f"Allowed entry!")

urls.py

from django.urls import path

from my_app import views

urlpatterns = [
    path("some-view/", views.SomeView.as_view()),
]

नमूना चलाना:

$ curl http://127.0.0.1:8000/my_app/some-view/?name=notme
You are forbidden here!
$ curl http://127.0.0.1:8000/my_app/some-view/?name=me
Allowed entry!
2
Niel Godfrey Ponciano 4 सितंबर 2021, 04:29

चूँकि ऐसा लगता है कि आप DRF का उपयोग कर रहे हैं, आप अपना खुद का प्रमाणीकरण वर्ग बना सकते हैं और वहां जेडब्ल्यूटी की प्रसंस्करण लागू कर सकते हैं:

from django.contrib.auth.models import AnonymousUser
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions


class MyCustomJWTAuthentication(BaseAuthentication):
    def authenticate(self, request):
        token = request.META['HTTP_AUTHORIZATION'].split(' ')[1]
        try:
            jwt.decode_cognito_jwt(token)
        except Exception:
            raise exceptions.AuthenticationFailed('Invalid JWT')

        return AnonymousUser(), None


class MyCustomAPIView(APIView):
    authentication_classes = (MyCustomJWTAuthentication, )

या यदि आप इसे सभी APIViews पर लागू करना चाहते हैं:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'path.to.MyCustomJWTAuthentication',
    ),
}

ध्यान दें कि एक बार JWT डिकोड विफल हो जाने पर, किसी अन्य प्रमाणीकरण वर्ग की जाँच नहीं की जाएगी। यदि आप यह नहीं चाहते हैं, तो except क्लॉज के लिए हैंडलिंग को AuthenticationFailed न बढ़ाने के लिए बदलें।

2
bdbd 1 सितंबर 2021, 04:49