我可以在一个站点中混合会话身份验证和令牌身份验证吗?

Joe*_*son 2 authentication django jwt django-rest-framework

我有使用会话身份验证的 django 应用程序。我需要添加 API 部分。此 API 将仅由我的 app.users(网络浏览器和移动设备)使用。我更喜欢对 API 使用令牌身份验证,因为它看起来更健壮。我发现rest_framework_jwt可以处理它。我的问题:我可以在一个站点中混合使用 Web 会话身份验证和 API 令牌身份验证吗?我认为 Web 应用程序和 API 应用程序是两个不同的应用程序。所以我想在我的项目中将它们分开,使用不同的子域并为每个使用不同类型的身份验证。是否可以按子域分离身份验证?我想在用户登录 Web 应用程序时发送令牌。这是个好主意吗?

Den*_*ehl 5

正如您在文档中看到的,您可以毫无问题地配置多个身份验证后端。DRF 只会尝试每个后端,直到有人说“好的”。

要记住的一件事:如果您(例如)提供无效的 JSON-Web-Token,那么身份验证将立即失败,并且不会尝试其他后端。很高兴rest_framework_jwt源代码中看到

def authenticate(self, request):
    """
    Returns a two-tuple of `User` and token if a valid signature has been
    supplied using JWT-based authentication.  Otherwise returns `None`.
    """
    auth = get_authorization_header(request).split()

    if not auth or auth[0].lower() != b'jwt':
        return None

    if len(auth) == 1:
        msg = 'Invalid JWT header. No credentials provided.'
        raise exceptions.AuthenticationFailed(msg)
    elif len(auth) > 2:
        msg = ('Invalid JWT header. Credentials string '
               'should not contain spaces.')
        raise exceptions.AuthenticationFailed(msg)

    try:
        payload = jwt_decode_handler(auth[1])
    except jwt.ExpiredSignature:
        msg = 'Signature has expired.'
        raise exceptions.AuthenticationFailed(msg)
    except jwt.DecodeError:
        msg = 'Error decoding signature.'
        raise exceptions.AuthenticationFailed(msg)

    user = self.authenticate_credentials(payload)

    return (user, auth[1])
Run Code Online (Sandbox Code Playgroud)
  • return None 意思是后端说:“这不是 JWT,让其他人试试
  • raise exceptions.AuthenticationFailed(msg) 意思是:“用户尝试了 JWT,但失败了。”

回答更多问题:

  • 无需在单独的应用程序中执行此操作(但如果您愿意,也没有问题)。
  • 正如您在“设置身份验证方案”中所读到的那样,您可以为身份验证后端定义全局默认值,但您也可以按View或覆盖它们ViewSet