繁体   English   中英

使用 Django REST Framework 的 TokenAuthentication 查询字符串中的令牌

[英]Token in query string with Django REST Framework's TokenAuthentication

在使用Django REST Framework构建的 API 中,可以使用 TokenAuthentication 方法完成身份验证。 它的文档说身份验证令牌应该通过Authorization标头发送。

通常可以通过查询字符串发送 API 密钥或令牌以进行身份​​验证,例如https://domain.com/v1/resource?api-key=lala

有没有办法对 Django REST Framework 的 TokenAuthentication 做同样的事情?

默认情况下,DRF 不支持查询字符串进行身份验证,但您可以轻松地在TokenAuthentication类中覆盖其authenticate方法以支持它。

一个例子是:

class TokenAuthSupportQueryString(TokenAuthentication):
    """
    Extend the TokenAuthentication class to support querystring authentication
    in the form of "http://www.example.com/?auth_token=<token_key>"
    """
    def authenticate(self, request):
        # Check if 'token_auth' is in the request query params.
        # Give precedence to 'Authorization' header.
        if 'auth_token' in request.query_params and \
                        'HTTP_AUTHORIZATION' not in request.META:
            return self.authenticate_credentials(request.query_params.get('auth_token'))
        else:
            return super(TokenAuthSupportQueryString, self).authenticate(request)
class QueryStringBasedTokenAuthentication(TokenAuthentication):
    def authenticate(self, request):
        key = request.query_params.get('auth_token').strip()
        if key:
            return self.authenticate_credentials(key)
        return False

DRF具有TokenAuthentication ,它在header查找token 方法authenticate_credentials负责验证令牌。

截至 2018 年,使用 Django Rest Framework,您可以创建自己的身份验证类,请参阅http://getblimp.github.io/django-rest-framework-jwt/#extending-jsonwebtokenauthentication

class JSONWebTokenAuthenticationQS(BaseJSONWebTokenAuthentication):
    def get_jwt_value(self, request):
        return request.QUERY_PARAMS.get('jwt')

然后在 APIView 类中添加authentication_classes = (JSONWebTokenAuthenticationQS,)

或者@authentication_classes((JSONWebTokenAuthenticationQS,))

在视图函数上。

跟进斯科特沃伦的回答。 这是朝着正确方向迈出的一步,因为 DRFJWT 文档不包括重要的 authentication_classes 行。 但是,正如问题 441 中所述,存在一个大问题,即您不能混合使用 JWT 身份验证方法。 我结束了:

class JSONWebTokenAuthenticationQS(JSONWebTokenAuthentication):
    def get_jwt_value(self, request):
        return request.GET.get('jwt') or JSONWebTokenAuthentication.get_jwt_value(self, request)

到目前为止似乎运作良好。 它使用 JSONWebTokenAuthentication 而不是 Base 类,因为它必须使用原始 get_jwt_value 方法。

参考OmriToptixScott Warren等网站12 的回答

现在大多数情况下使用JSONWebTokenAuthentication ,所以现在应该覆盖它的get_jwt_value ,完整代码是:

# from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import get_authorization_header

class JWTAuthByQueryStringOrHeader(JSONWebTokenAuthentication):
# class JWTAuthByQueryStringOrHeader(BaseJSONWebTokenAuthentication):
    """
    Extend the TokenAuthentication class to support querystring authentication
    in the form of "http://www.example.com/?jwt_token=<token_key>"
    """

    def get_jwt_value(self, request):
        # Check if 'jwt_token' is in the request query params.
        # Give precedence to 'Authorization' header.
        queryParams = request.query_params
        reqMeta = request.META

        if ('jwt_token' in queryParams) and ('HTTP_AUTHORIZATION' not in reqMeta):
            jwt_token = queryParams.get('jwt_token')
            # got jwt token from query parameter
            return jwt_token
        else:
            # call JSONWebTokenAuthentication's get_jwt_value
            # to get jwt token from header of 'Authorization'
            return super(JWTAuthByQueryStringOrHeader, self).get_jwt_value(request)

这里将上面的代码保存到apps/util/jwt_token.py ,然后不要忘记添加相关的Django设置:

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'apps.util.jwt_token.JWTAuthByQueryStringOrHeader',
        ...
    ),
    ...
}

现在前端/网络端可以像这样调用api:

http://localhost:65000/api/v1/scripts/3d9e77b0-e538-49b8-8790-60301ca79e1d/script_word_export/?jwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMWVkMGEwZDgtMmFiYi00MDFkLTk5NTYtMTQ5MzcxNDIwMGUzIiwidXNlcm5hbWUiOiJsc2R2aW5jZW50IiwiZXhwIjoxNTMxOTAyOTU0LCJlbWFpbCI6InZpbmNlbnQuY2hlbkBuYXR1cmxpbmcuY29tIn0.wheM7Fmv8y8ysz0pp-yUHFqfk-IQ5a8n_8OplbYkj7s

jwt_token传递到服务器端,获得下载/导出文件的授权。

同时仍然支持原始方法pass jwt token inside header 'Authorization'

POST http://localhost:65000/api/v1/scripts/3d9e77b0-e538-49b8-8790-60301ca79e1d/script_word_export/
Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMWVkMGEwZDgtMmFiYi00MDFkLTk5NTYtMTQ5MzcxNDIwMGUzIiwidXNlcm5hbWUiOiJsc2R2aW5jZW50IiwiZXhwIjoxNTMxOTAyOTU0LCJlbWFpbCI6InZpbmNlbnQuY2hlbkBuYXR1cmxpbmcuY29tIn0.wheM7Fmv8y8ysz0pp-yUHFqfk-IQ5a8n_8OplbYkj7s

暂无
暂无

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

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