繁体   English   中英

来自 DRF 的 React Native 401 未经授权的错误

[英]React Native 401 Unauthorized Error From DRF

我在 heroku 上的宁静 api (Django Rest API)在本地工作正常。 它目前部署在 heroku 上。 我正在使用本机应用程序与 API 进行交互。

每次我尝试检索经过身份验证的用户的详细信息时,首先返回详细信息,然后它会引发 401 错误....

我的申请流程是

  • 认证成功后

  • 保存用户的令牌

  • 检索经过身份验证的用户的详细信息

身份验证通过(经过身份验证的用户的详细信息也输出在日志上),但获取用户详细信息的位失败并出现 401 未授权

这是我在 heroku 上的服务器日志

2020-12-21T22:33:45.106941+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:33:45 +0000] "POST /api/accounts/token/ HTTP/1.1" 200 441 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"

2020-12-21T22:33:45.232882+00:00 heroku[router]: at=info method=PUT path="/api/accounts/token/device/" host=webapp.herokuapp.com request_id=4a5a06f9-ec50-4ecb-879e-20805784ba5c fwd="86.182.91.70" dyno=web.1 connect=0ms service=15ms status=200 bytes=255 protocol=https

2020-12-21T22:33:45.106757+00:00 heroku[router]: at=info method=POST path="/api/accounts/token/" host=webapp.herokuapp.com request_id=a4b7e5f6-1333-4b82-b180-12850391c382 fwd="86.182.91.70" dyno=web.1 connect=1ms service=399ms status=200 bytes=724 protocol=https

2020-12-21T22:33:45.232905+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:33:45 +0000] "PUT /api/accounts/token/device/ HTTP/1.1" 200 0 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"

2020-12-21T22:33:45.368821+00:00 app[web.1]: Unauthorized: /api/users/details/

2020-12-21T22:33:45.369671+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:33:45 +0000] "GET /api/users/details/ HTTP/1.1" 401 58 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"
2020-12-21T22:33:45.369458+00:00 heroku[router]: at=info method=GET path="/api/users/details/" host=webapp.herokuapp.com request_id=1de46c11-fa6d-4ebd-984e-40191239f031 fwd="86.182.91.70" dyno=web.1 connect=0ms service=5ms status=401 bytes=393 protocol=https


NOTICE THIS BIT HERE ( Which shows that the user is authorized )


2020-12-21T22:33:45.587452+00:00 app[web.1]:  26 
2020-12-21T22:33:45.587453+00:00 app[web.1]: False
2020-12-21T22:33:45.595378+00:00 app[web.1]: Below is the serializer response 
2020-12-21T22:33:45.595436+00:00 app[web.1]:  {'pk': 15, 'first_name': 'Test', 'middle_name': '', 'last_name': 'Ysgs', 'image': 'xxxxxxxxxxxx?AWSAccessKeyId=xxxxxxxxx&Signature=l4fHz7c%xxxxxxxx%3D&Expires=xxxxxxx', 'pref_address': None, 'can_request_delivery': True, 'account_type': 'Standard Account', 'phone_number': '+09082983928392', 'email': 'Aass@mail.com'} 


2020-12-21T22:33:45.596414+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:33:45 +0000] "GET /api/users/details/ HTTP/1.1" 200 395 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"
2020-12-21T22:33:45.596171+00:00 heroku[router]: at=info method=GET path="/api/users/details/" host=webapp.herokuapp.com request_id=d4c8a812-b9e0-4fb9-a273-5697af4513c4 fwd="86.182.91.70" dyno=web.1 connect=0ms service=15ms status=200 bytes=683 protocol=https

2020-12-21T22:34:15.197708+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:34:15 +0000] "POST /api/accounts/token/ HTTP/1.1" 200 441 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"

2020-12-21T22:34:15.341847+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:34:15 +0000] "PUT /api/accounts/token/device/ HTTP/1.1" 200 0 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"

2020-12-21T22:34:15.197578+00:00 heroku[router]: at=info method=POST path="/api/accounts/token/" host=webapp.herokuapp.com request_id=a33bddd3-b942-4126-95a4-18c36a722afe fwd="86.182.91.70" dyno=web.1 connect=0ms service=230ms status=200 bytes=724 protocol=https

2020-12-21T22:34:15.347870+00:00 heroku[router]: at=info method=PUT path="/api/accounts/token/device/" host=webapp.herokuapp.com request_id=28c0951c-3252-4a78-84b5-34b1609c8e42 fwd="86.182.91.70" dyno=web.1 connect=0ms service=16ms status=200 bytes=255 protocol=https

2020-12-21T22:34:15.550870+00:00 heroku[router]: at=info method=GET path="/api/users/details/" host=webapp.herokuapp.com request_id=c91941ef-cc54-4df9-bc44-56a5cf4e2839 fwd="86.182.91.70" dyno=web.1 connect=0ms service=5ms status=401 bytes=393 protocol=https




NOTICE THIS BIT HERE ( automatically makes says user is unauthorized )

2020-12-21T22:34:15.550059+00:00 app[web.1]: Unauthorized: /api/users/details/

2020-12-21T22:34:15.550879+00:00 app[web.1]: 10.43.233.181 - - [21/Dec/2020:22:34:15 +0000] "GET /api/users/details/ HTTP/1.1" 401 58 "-" "jisee/1 CFNetwork/1206 Darwin/20.1.0"

在我的 xCode 上,我在日志上看到了这个

2020-12-21 22:48:46.780760+0000 jisee[7365:1567414] [javascript] { [Error: Request failed with status code 401]
  config: 
   { url: 'https://webapp.herokuapp.com/api/users/details',
     method: 'get',
     headers: 
      { Accept: 'application/json, text/plain, /',
        Authorization: 'Bearer my-token-ViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTYInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTY' },
     transformRequest: [ [Function] ],
     transformResponse: [ [Function] ],
     timeout: 0,
     adapter: [Function],
     xsrfCookieName: 'XSRF-TOKEN',
     xsrfHeaderName: 'X-XSRF-TOKEN',
     maxContentLength: -1,
     maxBodyLength: -1,
     validateStatus: [Function: validateStatus],
     data: undefined },
  request: 
   { UNSENT: 0,
     OPENED: 1,
     HEADERS_RECEIVED: 2,
     LOADING: 3,
     DONE: 4,
     readyState: 4,
     status: 401,
     timeout: 0,
     withCredentials: true,
     upload: {},
     _aborted: false,
     _hasError: false,
     _method: 'GET',
     _perfKey: 'network_XMLHttpRequest_https://webapp.herokuapp.com/api/users/details',
     _response: '{"detail":"Authentication credentials were not provided."}',
     _url: 'https://webapp.herokuapp.com/api/users/details',
     _timedOut: false,
     _trackingName: 'unknown',
     _incrementalEvents: false,
     responseHeaders: 
      { 'Content-Type': 'application/json',
        'Www-Authenticate': 'Bearer realm="api"',
        Via: '1.1 vegur',
        Date: 'Mon, 21 Dec 2020 22:48:46 GMT',
        'Referrer-Policy': 'same-origin',
        Server: 'gunicorn/20.0.4',
        Connection: 'keep-alive',
        Allow: 'GET, HEAD, OPTIONS',
        'X-Content-Type-Options': 'nosniff',
        Vary: 'Accept, Origin',
        'Content-Length': '58',
        'X-Frame-Options': 'DENY' },
     _requestId: null,
     _cachedResponse: undefined,
     _headers: 
      { accept: 'application/json, text/plain, /',
        authorization: 'Bearer my-token-ViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTYNjc3MzI2LCJqdGkiOiI2Mjk4ZWFkNjAxZTE0NGNhYTljOWNmMjAwYTUwNDViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTY' },
     _responseType: '',
     _sent: true,
     _lowerCaseResponseHeaders: 
      { 'content-type': 'application/json',
        'www-authenticate': 'Bearer realm="api"',
        via: '1.1 vegur',
        date: 'Mon, 21 Dec 2020 22:48:46 GMT',
        'referrer-policy': 'same-origin',
        server: 'gunicorn/20.0.4',
        connection: 'keep-alive',
        allow: 'GET, HEAD, OPTIONS',
        'x-content-type-options': 'nosniff',
        vary: 'Accept, Origin',
        'content-length': '58',
        'x-frame-options': 'DENY' },
     _subscriptions: [],
     responseURL: 'https://webapp.herokuapp.com/api/users/details/' },
  response: 
   { data: { detail: 'Authentication credentials were not provided.' },
     status: 401,
     statusText: undefined,
     headers: 
      { 'content-type': 'application/json',
        'www-authenticate': 'Bearer realm="api"',
        via: '1.1 vegur',
        date: 'Mon, 21 Dec 2020 22:48:46 GMT',
        'referrer-policy': 'same-origin',
        server: 'gunicorn/20.0.4',
        connection: 'keep-alive',
        allow: 'GET, HEAD, OPTIONS',
        'x-content-type-options': 'nosniff',
        vary: 'Accept, Origin',
        'content-length': '58',
        'x-frame-options': 'DENY' },
     config: 
      { url: 'https://webapp.herokuapp.com/api/users/details',
        method: 'get',
        headers: 
         { Accept: 'application/json, text/plain, /',
           Authorization: 'Bearer my-token-ViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTYl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjA4Njc3MzI2LCJqdGkiOiI2Mjk4ZWFkNjAxZTE0NGNhYTljOWNmMjAwYTUwNDViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTY' },
        transformRequest: [ [Function] ],
        transformResponse: [ [Function] ],
        timeout: 0,
        adapter: [Function],
        xsrfCookieName: 'XSRF-TOKEN',
        xsrfHeaderName: 'X-XSRF-TOKEN',
        maxContentLength: -1,
        maxBodyLength: -1,
        validateStatus: [Function: validateStatus],
        data: undefined },
     request: 
      { UNSENT: 0,
        OPENED: 1,
        HEADERS_RECEIVED: 2,
        LOADING: 3,
        DONE: 4,
        readyState: 4,
        status: 401,
        timeout: 0,
        withCredentials: true,
        upload: {},
        _aborted: false,
        _hasError: false,
        _method: 'GET',
        _perfKey: 'network_XMLHttpRequest_https://webapp.herokuapp.com/api/users/details',
        _response: '{"detail":"Authentication credentials were not provided."}',
        _url: 'https://webapp.herokuapp.com/api/users/details',
        _timedOut: false,
        _trackingName: 'unknown',
        _incrementalEvents: false,
        responseHeaders: 
         { 'Content-Type': 'application/json',
           'Www-Authenticate': 'Bearer realm="api"',
           Via: '1.1 vegur',
           Date: 'Mon, 21 Dec 2020 22:48:46 GMT',
           'Referrer-Policy': 'same-origin',
           Server: 'gunicorn/20.0.4',
           Connection: 'keep-alive',
           Allow: 'GET, HEAD, OPTIONS',
           'X-Content-Type-Options': 'nosniff',
           Vary: 'Accept, Origin',
           'Content-Length': '58',
           'X-Frame-Options': 'DENY' },
        _requestId: null,
        _cachedResponse: undefined,
        _headers: 
         { accept: 'application/json, text/plain, /',
           authorization: 'Bearer my-token-ViZCIsInVzZXJfaWQiOjI2fQ.3-xy4vMiqa4qCiCC6nD3lQY6_-GXv-ARau2HbfTTY' },
        _responseType: '',
        _sent: true,
        _lowerCaseResponseHeaders: 
         { 'content-type': 'application/json',
           'www-authenticate': 'Bearer realm="api"',
           via: '1.1 vegur',
           date: 'Mon, 21 Dec 2020 22:48:46 GMT',
           'referrer-policy': 'same-origin',
           server: 'gunicorn/20.0.4',
           connection: 'keep-alive',
           allow: 'GET, HEAD, OPTIONS',
           'x-content-type-options': 'nosniff',
           vary: 'Accept, Origin',
           'content-length': '58',
           'x-frame-options': 'DENY' },
        _subscriptions: [],
        responseURL: 'https://webapp.herokuapp.com/api/users/details/' } },
  isAxiosError: true,
  toJSON: [Function] }

API URL 构造

from django.urls import path
from rest_framework import routers
from .api import views as apiview


router = routers.DefaultRouter()
router.register(r'', apiview.UserViewSet)


app_name = 'users'
urlpatterns = router.urls

API 查看代码

class UserViewSet(BaseViewSet):
    """Contains set of views that processes request to manipulate
    user's data
    """
    model = User
    look_up_field = 'pk'
    queryset = User.objects.all()
    serializer_class = UserSerializer
    parser_classes = [
        parsers.MultiPartParser,
        parsers.FormParser,
        parsers.JSONParser,
    ]
    permission_class_kwargs = {
        "list":(permissions.IsAuthenticated,custom_perms.IsOperationStaff,),
        "create": (permissions.AllowAny, ),
        "retrieve":(permissions.IsAuthenticated, ),
        "destroy": (permissions.IsAuthenticated, custom_perms.IsMyAccount,),
        "update": (permissions.IsAuthenticated, custom_perms.IsMyAccount,)
    }
    
    @action(
        detail=False,
        methods=['GET'],
        url_name='details',
        url_path='details',
        permission_classes=[permissions.IsAuthenticated]
    )            
    def details(self, request):
        """Returns the details of authenticated user account"""
        print("\n\n\n", request.user.pk, "\n\n\n\n")
        print(request.user.pk == None)
        print("\n\n\n\n\n")
        

        serializer = self.serializer_class(request.user.me)
        print("Below is the serializer response \n\n\n",
            serializer.data, "\n\n\n\n\n\n")
        return Response(serializer.data, status=status.HTTP_200_OK)

以下是我的要求

react-native: "0.63.3",      
axios: "^0.21.0",
Django==3.1.1
django-heroku==0.3.1
djangorestframework==3.11.1
djangorestframework-gis==0.16
djangorestframework-simplejwt==4.3.0

观察

我可以使用 postman 客户端、cURL、python 向 heroku 服务器上的同一端点发出请求,并将得到有效响应(从未经历过来自上述客户端的 401 未经授权)

请问我该如何解决这个问题?

已编辑(编辑 01)

添加我的宁静 api 视图,输出经过身份验证的用户的详细信息

已编辑(编辑 02)

===================

我为用户手动创建令牌,因为有各种帐户类型,每个身份验证都不同。 下面是我如何处理认证片

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    fb_token = serializers.CharField(required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['password'] = PasswordField()
        self.fields['phone'] = serializers.CharField(required=False)
        self.fields['email'] = serializers.CharField(required=False)
        self.fields['fb_token'] = serializers.CharField(required=False)
        self.user = None

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        return token

    def validate(self, attrs):
        """Validates provided incredentials for authentication. 

        Provides mechanism to authenticate through phone and email.
        For phone authentication, firebase token is needed to fully 
        authenticate the request. Password not required here

        For email authentication, request will only be validated if
        a valid and existent email and password is provided.

        If invalid credentials are passed, authentication will fail.
        """
        auth_type = auth_services.check_auth_type(attrs)
        if type(auth_type) is str:
            
            if auth_type == "phone":
                tokens_or_none = auth_services.phone_auth_service(
                    phone=attrs.get('phone'), fb_token=attrs.get('fb_token'),
                    request=self.context.get('request', None),
                )
                return tokens_or_none

            elif auth_type == "email":
                return super().validate(attrs)

        return auth_type

要列出用户信息,您有权限:

"list":(permissions.IsAuthenticated,custom_perms.IsOperationStaff,),

您的用户是OperationStaff吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM