使用Django表单向导实现登录页面的安全双因素身份验证

使用Django表单向导实现登录页面的安全双因素身份验证,django,authentication,django-formwizard,Django,Authentication,Django Formwizard,所以基本上我想实现一些类似于Google双因素身份验证的实现。我的登录表单由两步表单向导组成: 步骤1(验证用户名和密码) 步骤2(验证安全令牌) 使用场景为: 用户具有与其帐户关联的安全令牌:如果用户通过步骤1和步骤2,则登录用户 用户没有安全令牌:仅在用户通过步骤1后立即登录 我现在正在将django的表单向导子类化,以用作我的登录视图。在步骤2中,默认情况下,Django FormWizard将以前提交的表单中的字段值作为隐藏字段包含在内。但正如您所知,密码是在步骤1中输入的,因此出于安全

所以基本上我想实现一些类似于Google双因素身份验证的实现。我的登录表单由两步表单向导组成:

  • 步骤1(验证用户名和密码)
  • 步骤2(验证安全令牌)
  • 使用场景为:

  • 用户具有与其帐户关联的安全令牌:如果用户通过步骤1和步骤2,则登录用户
  • 用户没有安全令牌:仅在用户通过步骤1后立即登录
  • 我现在正在将django的表单向导子类化,以用作我的登录视图。在步骤2中,默认情况下,Django FormWizard将以前提交的表单中的字段值作为隐藏字段包含在内。但正如您所知,密码是在步骤1中输入的,因此出于安全原因,我不想将其包括在步骤2中

    我的第一个想法是使用session来指示用户是否通过了步骤1,所以我不需要包含步骤1中的字段值。。但我可能忽略了一些东西。有哪些更安全的解决方案

    另外,我不太了解FormWizard中安全哈希的用法。有人能解释一下吗


    非常感谢。

    我并不完全理解安全令牌的意义,但是如果您放弃扩展
    FormWizard
    并将其作为两个独立的视图来实现,它看起来会更简单、更快。
    FormWizard
    的全部要点是将多个表单分解并聚合为一个表单,而您的特定用例与此背道而驰—您可能只是在对其进行黑客攻击,以便在功能上做一些其他事情

    至于安全散列,它为成功完成的步骤中的所有表单数据计算一个散列。这只是一种安全措施,以确保表单数据在两个步骤之间没有更改/被篡改,并且没有任何步骤以其他方式被绕过。

    Duo security的项目有一个可向您展示执行此操作的方法(我是Duo开发人员)

    演示设置有一个@duo_auth_required decorator,类似于内置的@login_required,它检查会话cookie,指示用户已通过第二因素身份验证。@login\u required decorator验证本地身份验证,@duo\u auth\u required decorator验证第二因素身份验证,缺少这两个因素都会将用户重定向到相关表单


    与您的描述不同的是,我们不在单个表单中同时进行身份验证,也不在表单之间传递凭据,而是分别进行验证。只需使用两个decorator保护一个视图,您就可以依靠Django在尝试第二因子身份验证之前断言本地身份验证。

    该项目向Django添加了可插入的双因子身份验证。它可以在不同的层次上集成,从视图到表单再到低级API。

    在最后一个答案出现一年多后:


    建立在django otp之上,并添加了对Google Authenticator、Twilio SMS和备份代码的开箱即用支持。非常令人印象深刻。

    您可以使用现有的多因素身份验证后端,如LinOTP或。
    我创建了一个writeup。

    如果您还没有签出Google的双因素身份验证,这里的安全令牌是一个依赖于时间的一次性密码。我现在同意FormWizard不是我所需要的,因为我最多只需要2个表单,有时只需要1个表单。我继续在两个不同的视图中实现了我的表单。谢谢。顺便说一句,我还需要某种形式的安全哈希吗?现在,如果用户已经通过了步骤1,我编写了一个中间会话来表明这一点。我只在用户通过第2步(登录成功)后删除会话。这种方法足够安全吗?谢谢。可以说它坚如磐石。中间会话保证用户成功通过第一步。只要您根据已验证的数据生成,即用户以成功验证的形式传递,我就看不出有人会如何危害您的身份验证系统。django示例的新url为: