首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用任何url上的查询参数验证用户?

如何使用任何url上的查询参数验证用户?
EN

Stack Overflow用户
提问于 2020-05-26 14:33:40
回答 3查看 2.3K关注 0票数 2

假设用户在https://example.com/any/page?token=hhdo28h3do782上登陆。

使用查询字符串对用户进行身份验证和登录的推荐方法是什么?

我正在考虑创建一个调用authenticate()的完全捕获视图(我也想知道如何做到这一点:D)。然后,我将设置一个自定义后端来验证用户。

这是实现我想要的理想的方式吗?

干杯!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-05-26 15:16:31

为此,您需要验证api键的创建自定义身份验证后端

在本例中,将自动检查request是否为有效的令牌()。您根本不需要修改和修改您的视图。这是因为它包括对用户进行身份验证的自定义中间件。

为了简洁起见,我假设有效的用户令牌存储在一个模型中,该模型的外键指向django auth.User模型。

代码语言:javascript
复制
# my_project/authentication_backends.py
from django.contrib import auth
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.contrib.auth.middleware import AuthenticationMiddleware

TOKEN_QUERY_PARAM = "token"

class TokenMiddleware(AuthenticationMiddleware):
    def process_request(self, request):
        try:
            token = request.GET[TOKEN_QUERY_PARAM]
        except KeyError:
            # A token isn't included in the query params
            return

        if request.user.is_authenticated:
            # Here you can check that the authenticated user has the same `token` value
            # as the one in the request. Otherwise, logout the already authenticated
            # user.
            if request.user.token.key == token:
                return
            else:
                auth.logout(request)

        user = auth.authenticate(request, token=token)
        if user:
            # The token is valid. Save the user to the request and session.
            request.user = user
            auth.login(request, user)

class TokenBackend(ModelBackend):
    def authenticate(self, request, token=None):
        if not token:
            return None

        try:
            return User.objects.get(token__key=token)
        except User.DoesNotExist:
            # A user with that token does not exist
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

现在,除了已有的任何后端或中间件之外,您还可以在AUTHENTICATION_BACKENDSMIDDLEWARE中添加到settings.py的路径。如果使用的是默认值,则如下所示:

代码语言:javascript
复制
MIDDLEWARE = [
    # ...
    "django.contrib.auth.middleware.AuthenticationMiddleware",

    # This is the dotted path to your backend class. For this example,
    # I'm pretending that the class is in the file:
    #     my_project/authentication_backends.py
    "my_project.authentication_backends.TokenMiddleware",

    # ...
]

AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "my_project.authentication_backends.TokenBackend",
]
票数 3
EN

Stack Overflow用户

发布于 2020-05-26 14:47:17

我假设您正在使用Django REST框架,并且在您的项目中启用了TokenAuthentication机制。如果是这样的话,那就这么做吧,

代码语言:javascript
复制
from rest_framework.authentication import TokenAuthentication


class QueryParamAuthentication(TokenAuthentication):
    query_param_name = 'token'

    def authenticate(self, request):
        token = request.query_params.get(self.query_param_name)
        if token:
            return self.authenticate_credentials(token)
        return None

然后,将DRF DEFAULT_AUTHENTICATION_CLASSES更改为

代码语言:javascript
复制
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'dotted.path.to.QueryParamAuthentication'
    ),
    # rest of your DRF settings...

}

更新

要做到这一点,没有DRF,您必须编写自定义模型后端(这是一个有点长的主题)。

参考编写身份验证后端

票数 2
EN

Stack Overflow用户

发布于 2020-05-26 14:57:03

所以,从一种管理令牌的方法开始。下面是一个基本模型:

代码语言:javascript
复制
class Token(models.Model):
    code = models.CharField(max_length=255)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    expires = models.DateTimeField()

可以产生一个自定义身份验证后端来检查令牌的有效性:

代码语言:javascript
复制
class TokenAuthenticationBackend(ModelBackend):
    def authenticate(self, request, token=None):
        try:
            token = Token.objects.get(code=token, expires__gte=now())
        except Token.DoesNotExist:
            return None
        else:
            return token.user

如果使用的是基于类的视图,则可以编写一个混合体,检查令牌是否存在,然后执行身份验证逻辑:

代码语言:javascript
复制
class UrlTokenAuthenticationMixin:
    def dispatch(self, request, *args, **kwargs):
        if 'token' in request.GET:
            user = authenticate(request, request.GET['token'])
            if user:
                login(request, user)
        return super(UrlTokenAuthenticationMixin, self).dispatch(request, *args, **kwargs)

若要在给定视图上使用此操作,只需按以下方式声明视图:

代码语言:javascript
复制
class MyView(UrlTokenAuthenticationMixin, TemplateView):
    # view code here

例如。

实现这一点的另一种方法是使用中间件,而不是混合:

代码语言:javascript
复制
class TokenAuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if 'token' in request.GET:
            user = authenticate(request, request.GET['token'])
            if user:
                login(request, user)
        return self.get_response(request)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62024580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档