URL token authentication in Django

2019-03-01 13:47发布

I'm looking for a way in which I can send out a user an email with a url that will log them into their user. This doesn't even necessarily have to expire. I have found tons of material on sessions however this is not what I'm after. What I need is this:

  • User submits something to the website
  • They have an account made in the background
  • An email is sent out containing a link "site.com/&token=foobar23124123"
  • The user can log in using that link (optional: for the next week)

Is there something out there that I'm missing that would help me or would I have to implement my own solution? Could I potentially just include the token from Django REST framework's Tokens?

Thank you for taking the time to read my question.

I'm Using Django 1.9 and Python 2.7

1条回答
太酷不给撩
2楼-- · 2019-03-01 14:38

I don't think there is something for authenticating users using url get-parameters. AFAIK Django REST framework's Tokens uses HTTP headers for tokens.

You can write your own auth backend, it's quite easy. Here is an example

myproject/setting.py

AUTHENTICATION_BACKENDS = [
    'myproject.backends.UrlTokenBackend',
    'django.contrib.auth.backends.ModelBackend'
]

myproject/backends.py

class UrlTokenBackend(ModelBackend):
    def authenticate(self, token):
        try:
            user = User.objects.get(token=token)
        except User.DoesNotExist:
            return None

        if not user.is_active:
            return None

        return user

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

Now when you will call authenticate and login function Django will check your user against each of your backends. You can manually login user like this (this is view function):

from django.contrib.auth import authenticate, login

def user_auth(request):
    token = request.GET.get('token')
    user = authenticate(token=token)
    login(request, user)

    return redirect('index')

Update

Or you can use this hack and do only this (without custom backend):

def user_auth(request):
    token = request.GET.get('token')
    user = User.objects.get(token=token)
    user.backend = 'django.contrib.auth.backends.ModelBackend'
    login(request, user)

    return redirect('index')
查看更多
登录 后发表回答