简体   繁体   English

Django - 双因素身份验证自定义登录

[英]Django - Two Factor Authentication Custom Login

After a quick search and reading documentation I implemented Django - Two Factor Authentication in one of my Django project [ Reference Link ].在快速搜索和阅读文档后,我在我的 Django 项目 [参考链接] 之一中实施了 Django - 双因素身份验证。

It works great I am using Google Authenticator for token based login.效果很好 我正在使用 Google Authenticator 进行基于令牌的登录。 The problem arises when I want to extend login methodology of the library.当我想扩展图书馆的登录方法时,问题就出现了。 I want to enforce my every user to use 2-Factor-Auth as compulsion.我想强制我的每个用户强制使用 2-Factor-Auth。 I am not using any signup measures so there has to be a check at the time of Login for a user.我没有使用任何注册措施,因此必须在用户登录时进行检查。

The problem is to design a custom login mechanism but I am unable to incorporate this library with the custom login.问题是设计一个自定义登录机制,但我无法将这个库与自定义登录结合起来。

PS: I have a custom user model and currently I am using default Login that came with Django Two Factor Authentication. PS:我有一个自定义用户 model,目前我使用的是 Django 双因素身份验证附带的默认登录名。

I did not though the code was necessary so I did not posted it but I can share it if needed.虽然代码不是必需的,但我没有发布它,但如果需要我可以分享它。

After a through look at the library code I was able to manipulate the check in the two_factor library.通过查看库代码后,我能够操作 two_factor 库中的检查。

So, looking at two_factor folder it is easily understandable that is nothing but a Django app similar to others.因此,查看two_factor文件夹很容易理解,它只不过是一个类似于其他应用程序的 Django 应用程序。

I navigated to the library files in my virtual environment venv\Lib\site-packages\two_factor\views\core.py .我导航到我的虚拟环境venv\Lib\site-packages\two_factor\views\core.py中的库文件。 As mentioned in the documentation there is no enforcement for users till now to setup 2fa.如文档中所述,到目前为止,用户还没有强制执行设置 2fa。

In LoginView(...) there is a function done .LoginView(...)中有一个 function done IT checks for the device availability for 2fa just add a else clause for redirection. IT 检查 2fa 的设备可用性只需添加一个 else 子句进行重定向。

def done(self, form_list, **kwargs):
        """
        Login the user and redirect to the desired page.
        """

        # Check if remember cookie should be set after login
        current_step_data = self.storage.get_step_data(self.steps.current)
        remember = bool(current_step_data and current_step_data.get('token-remember') == 'on')

        login(self.request, self.get_user())

        redirect_to = self.get_success_url()

        device = getattr(self.get_user(), 'otp_device', None)
        response = redirect(redirect_to)

        if device:
            signals.user_verified.send(sender=__name__, request=self.request,
                                       user=self.get_user(), device=device)

            # Set a remember cookie if activated

            if getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_AGE', None) and remember:
                # choose a unique cookie key to remember devices for multiple users in the same browser
                cookie_key = REMEMBER_COOKIE_PREFIX + str(uuid4())
                cookie_value = get_remember_device_cookie(user=self.get_user(),
                                                          otp_device_id=device.persistent_id)
                response.set_cookie(cookie_key, cookie_value,
                                    max_age=settings.TWO_FACTOR_REMEMBER_COOKIE_AGE,
                                    domain=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_DOMAIN', None),
                                    path=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_PATH', '/'),
                                    secure=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_SECURE', False),
                                    httponly=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_HTTPONLY', True),
                                    samesite=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_SAMESITE', 'Lax'),
                                    )
        else:
            return redirect('two_factor:setup')

        return response

So what happens is the check for device can only be successful if the user has setup the 2fa but it will never be true for unverified user.因此,只有在用户设置了 2fa 的情况下,设备检查才能成功,但对于未经验证的用户永远不会成功。

I totally understand there will be a more efficient and elegant method to do the above task but with my little knowledge and time limitation I have to do this.我完全理解将有一种更有效、更优雅的方法来完成上述任务,但由于我的知识和时间限制,我必须这样做。 I will post an update if I encounter and I also welcome feedbacks for my solution.如果我遇到,我会发布更新,我也欢迎为我的解决方案提供反馈。

django-two-factor-auth provides an is_verified() method through django-otp 's OTPMiddleware . django-two-factor-auth通过django-otpOTPMiddleware提供了一个is_verified()方法。 According to the docs , this method根据文档,这种方法

can be used to check if the user was logged in using two-factor authentication.可用于检查用户是否使用双重身份验证登录。

I have a similar scenario as yours (Custom User Model and django-two-factor-auth 's default login mechanism), so I did the following:我有一个和你类似的场景(自定义用户 Model 和django-two-factor-auth的默认登录机制),所以我做了以下事情:

  1. set LOGIN_REDIRECT_URL to a URL which requires a verified user.LOGIN_REDIRECT_URL设置为需要经过验证的用户的 URL。 Let's call it, for example, "dashboard"让我们称之为,例如, "dashboard"
  2. in the dashboard view, do something like this:在仪表板视图中,执行以下操作:
def dashboard_view(request):
    if request.user.is_verified():
        # user logged in using two-factor
        return render(request, "dashboard/template.html")
    else:
        # user not logged in using two-factor
        return redirect("two_factor:setup")

The contribution from 'engineervix' was very useful, however, it can be simply bypassed by a single authentication and tyting in a known django web address. 'engineervix' 的贡献非常有用,但是,它可以通过单个身份验证和在已知的 django web 地址中输入来简单地绕过。 However, this is a first super step.然而,这是超级第一步。 Combined with a standart base.html with a check on 'request.user.is_verified', it seems to me like a complete solution.结合标准 base.html 并检查“request.user.is_verified”,在我看来这是一个完整的解决方案。 I attach my base.html as an example.我附上我的 base.html 作为示例。

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="de">
<head>
  ...
</head>
<body>
  <div class="container">
    <header class="p-3 mb-3 border-bottom">
     
          {% if request.user.is_verified %}
            <a class="navbar-brand" href="{% url 'home' %}">
              Sample Site Title</a>
          {% else %}
            <h3 style="color:blue;">Sample Site Tile</h3>
          {% endif %}
    </header>
  <main>
    {% if request.user.is_verified %}
      {% block content %}
      {% endblock %}
    {% else %}
      <h3>You are not logged in</h3>
      {% block content_non_auth %}
        <!-- Block for user accout management without 2FA -->`enter code here`
      {% endblock %}
    {% endif %}
  </main>
</body>

</html>

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

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