繁体   English   中英

Django DRF令牌认证

[英]Django DRF Token Authentication

我在DRF基于令牌的身份验证时遇到问题。 以下是我的目标网页代码(登录后):

@api_view(['GET','POST'],)
def landing(request):
    this_tenant=request.user.tenant
    end=date_first.date.today()
    start=end-date_first.timedelta(days=30)
    sales_daily=sales_day_wise(start, end, this_tenant)
    invoice_value=sales_raised_value(start, end, this_tenant)
    payment_value=sales_collected_value(start, end, this_tenant)
    return render(request,'landing.html', {'sales_daily':json.dumps(sales_daily, cls=DjangoJSONEncoder),\
        'invoice_value':json.dumps(invoice_value, cls=DjangoJSONEncoder), \
        'payment_value':json.dumps(payment_value, cls=DjangoJSONEncoder)})

我使用Django的内置登录视图对用户进行身份验证和登录,然后进行了修改以考虑将令牌放入标头中。 但这也不起作用

这是我的登录代码:

#Redirect authenticated users to landing page
def custom_login(request):
    if request.user.is_authenticated():
        token, created = Token.objects.get_or_create(user=request.user)
        request.session['AUTHORIZATION'] = "TOKEN "+token.key
        return redirect(landing)
    else:
        return login(request)

以下是我的DRF设置:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        # 'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

问题是,当我通过浏览器登录并进入登录页面时,DRF无法正常工作,并且出现以下错误:

{"detail":"Authentication credentials were not provided."}

原因是请求中不存在自定义DRF标头(AUTHENTICATION = TOEKN XXXXXXXXXX)。

但是,如果我使用Postman并放入自定义标头(AUTHENTICATION = TOKEN XXXXXXXXXXXX),则它可以工作。

我该如何解决?

这是否意味着每个视图都需要自定义标题?

在使用DRF令牌时,是否会打开CSRF漏洞(此问题: Django DRF-如何使用令牌身份验证进行CSRF验证 )?

非常感谢!!

  • 我该如何解决? 这是否意味着每个视图都需要自定义标题? TokenAuthentication用于Single Page App,并且请求标头中的令牌需要由API客户端(邮递员,Javascript或任何其他客户端)在每个请求上提供。 对于您的情况,如果要使用Django视图,则应激活SessionAuthentication。 令牌认证和会话认证可以共存。 一种方法是将令牌保存在自定义登录视图中的cookie中,并由javascript客户端读取。

  • 使用DRF令牌时,是否会打开CSRF漏洞(此问题:Django DRF-如何使用令牌身份验证进行CSRF验证)? 是。 但是,有一些方法可以保护请求。 根据DRF文档“如果在生产中使用令牌身份验证,则必须确保您的API仅可通过https使用”。 另外,请确保在设置中将ALLOWED_HOSTS设置为您希望Django响应的域,以便服务器不响应其他来源的请求。 除了令牌身份验证(如上面提到的JWT)之外,还可以使用其他更安全的Auth。

您需要先学习基础知识。 什么是HTTP,什么是HTTP标头,什么是Django会话(这不是HTTP标头,并且该会话的内容不会影响标头),请阅读有关令牌认证的Django REST Framework文档。

如果要在浏览器中测试视图,请在DRF DEFAULT_AUTHENTICATION_CLASSES配置变量中显式允许Django会话身份验证。 它可以与令牌认证共存。

除非您使用诸如RESTClient,DHC或REST Easy之类的插件,否则无法使普通的Web浏览器将令牌附加到HTTP请求。

您正在将令牌添加到Django会话中,但是您已在DRF中禁用了会话身份验证,即使您启用了该身份验证,DRF也不会从Django会话中读取令牌,因为API客户端无法将令牌添加到Django会话中。 即使DRF会从Django会话中读取令牌,这也完全没有意义,因为客户端无法控制会话的内容。 会话变量是在服务器上设置的,而不是在客户端上设置的。

REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ],
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.BasicAuthentication',  # enables simple command line authentication
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.TokenAuthentication',
        )
    }

大多数情况下,添加'rest_framework.authentication.SessionAuthentication'可以解决此问题。

另类

您可以使用:

'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
   ),

但是现在,为了访问受保护的api网址,您必须包含Authorization:JWT标头。

如果它适用于curl或邮递员,则表明后端不是问题。 客户端代码当然是一个问题。 您是否看过对REST api的请求? 我建议并确保令牌在标头中传递并正确设置格式。

暂无
暂无

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

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