【问题标题】:Implement "Remember Me" Django实现“记住我”Django
【发布时间】:2015-08-06 08:10:05
【问题描述】:

我目前正在尝试在 Django 中实现“记住我”功能。

我同时使用来自 Django REST 框架的 SessionAuthentication 和来自 djangorestframework-jwt 的 JSONWebTokenAuthentication

但是,我不知道如何为这两个身份验证实现“记住我”的概念。就像我如何永远扩展会话以及如何永远扩展令牌(我正在使用 JWT auth for mobile & desktop - Session auth for browser)。

另外,为两种身份验证实现此功能的安全方法是什么?

【问题讨论】:

    标签: python django authentication django-rest-framework jwt


    【解决方案1】:

    依赖关系

    from django.shortcuts import render
    from django.http import JsonResponse
    from django.views.decorators.csrf import csrf_exempt
    from django.contrib.auth import authenticate
    from site_user.models import User
    

    当我们在登录页面时,此代码将从会话中撤销用户名和密码

    def home(request):
        if request.session.has_key('username') and request.session.has_key('password'):
            username = request.session['username']
            password = request.session['password']
            context_dict = {'username': username, 'password': password}
            return render(request, 'sadmin/login.html', context=context_dict)
        else:
            context_dict = {'username': '', 'password': ''}
            return render(request, 'sadmin/login.html', context=context_dict)
    

    以下代码用于用户认证。这里是 HTML 文件中的“is_remember_check”复选框字段

    @csrf_exempt
    def login(request):
        if request.method == "POST":
            if request.POST['is_remember_check'] == 'true':
                request.session['username'] = request.POST['username']
                request.session['password'] = request.POST['password']
    
            user = authenticate(username=request.POST['username'], password=request.POST['password'])
    
            if user is not None:
                return JsonResponse({'result': request.POST, 'status': True})
            else:
                return JsonResponse({'result': request.POST, 'status': False})
    

    来自登录页面的 AJAX 调用

    function login(){
        remember_checkbox_value = document.getElementsByName('remember')[0].checked;
        username = document.getElementsByName('username')[0].value;
        password = document.getElementsByName('password')[0].value;
        var post_data = {username:username, password:password, is_remember_check:remember_checkbox_value};
    
        $.ajax({
                    url: '/sadmin/login/',
                    method: 'POST',
                    data: post_data,
                    dataType: 'json',
                    success: function (response) {
                            if (response.status){
                            alert("User login is successful");
                            window.location.reload();
                            }
                            else{
                            alert("User login is not successful");
                            window.location.reload();
                            }
                    }
            });
    }
    

    HTML 代码

    <div class="form-actions">
                <label class="checkbox">
                <input type="checkbox" name="remember"/> Remember me </label>
                <button type="button" class="btn green-haze pull-right" onclick="login()">Login <i class="m-icon-swapright m-icon-white"></i>
                </button>
            </div>
    

    【讨论】:

      【解决方案2】:

      在设置文件中你必须设置:

      SESSION_EXPIRE_AT_BROWSER_CLOSE = True
      

      在模板中:

      提供一个带有 name="remember_me" value="1" 的复选框

      在登录函数(view.py 或 ajax.py)中,当用户名和密码匹配时编写此代码,

      try:
          remember = request.POST['remember_me']
          if remember:
              settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False
      except MultiValueDictKeyError:
          is_private = False
          settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = True
      

      【讨论】:

      • 不确定实时修改设置是否是个好主意。设置应该是全局常量。
      • @AntoinePinsard 是对的。不应从代码修改设置。
      • 此代码不仅会更改您的一个客户端的设置,还会更改整个服务器的设置。
      【解决方案3】:

      这里有几件事我应该提前说明:身份验证的工作原理以及SessionAuthenticationJSONWebTokenAuthentication 的到期在哪里发挥作用。

      会话认证

      Django REST 框架提供的SessionAuthentication 类实际上只是session framework provided by Django 之上的一小层。因此,如果您可以使用他们的会话在 Django 中实现“记住我”功能,DRF 也会继承它。

      幸运的是,有人已经在 Stack Overflow 上询问过这个问题:Django “Remember Me” with built-in login view and authentication form

      基本上,它归结为将the SESSION_COOKIE_AGE setting(默认为 2 周)更改为一个非常高的数字。还请务必牢记长期会话的含义,并可能查看会话 cookie 在您访问的网站上的默认时长(通常为 2 周到 6 个月)。

      JSON 网络令牌

      django-rest-framework-jwt 提供的JSONWebToken 身份验证类基于 JSON Web 令牌对请求进行身份验证。默认情况下,令牌会在 5 分钟后过期,但最长可以刷新 7 天。

      令牌过期时间由JWT_EXPIRATION_DELTA 设置控制。不建议将这个时间延长太大,而是use refresh tokens 用于长寿命令牌。您可以使用JWT_ALLOW_REFRESH 设置启用刷新令牌,并使用JWT_REFRESH_EXPIRATION_DELTA 设置控制过期时间。

      【讨论】:

      • 那么对于使用 JWT 与服务器通信的移动或桌面应用程序,我是否应该将用户名和密码存储在本地数据库中并继续请求“记住我”功能的令牌?还是我应该只保存令牌,但使用 1 天这样的到期时间并保持刷新?
      • @TimNguyen 我强烈建议将刷新令牌存储在本地数据库中。以纯文本(或什至轻度加密)存储他们的用户名和密码是有风险的,存储一个易于撤销的过期令牌没有那么危险
      • django-rest-framework-jwt 不会给我 refresh_token ,这让我发疯了!我将JWT_ALLOW_REFRESH 属性设置为True 并设置JWT_REFRESH_EXPIRATION_DELTA 很长时间。我期望的行为是得到refresh_token,但这并没有发生。在达到JWT_EXPIRATION_DELTA 后,我获得的一个令牌不适用于令牌刷新。我错过了什么吗?
      猜你喜欢
      • 2012-08-08
      • 1970-01-01
      • 2011-02-15
      • 2017-06-14
      • 2018-09-05
      • 2013-12-16
      • 1970-01-01
      • 2011-08-02
      • 2016-04-11
      相关资源
      最近更新 更多