FA有许多不同的形式生java

时间:2021-09-15
本文章向大家介绍FA有许多不同的形式生java,主要包括FA有许多不同的形式生java使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

支持双因素身份验证(2FA)几乎总是一个好主意,特别是对于后台系统。2 FA有许多不同的形式,其中有些包括SMS、TOTP,甚

启用它们需要类似的流程:

  • 用户转到他们的配置文件页面(如果您想在注册时强制2FA,请跳过这个页面)
  • 单击“启用双因素身份验证”。
  • 输入一些数据以启用特定的2FA方法(电话号码、TOTP验证代码等)
  • 下次登录时,除了用户名和密码外,登录表单请求第二个因素(验证代码),并将其连同凭据一起发送。

我将重点介绍Google身份验证器,它使用一个基于时间的一次性密码(TOTP)来生成一系列验证代码。其思想是服务器和客户端应用程序共享一个秘密密钥。基于该键和当前时间,两者提出了相同的代码。当然,时钟并不是完全同步的,所以服务器接受的一些代码窗口是有效的。请注意,如果您不信任Google的应用程序,您可以使用下面相同的库实现自己的客户端应用程序(尽管您可以看到确保不发生恶作剧)。

如何用Java(在服务器上)实现这一点?使用流动情况如下:

https://www.jianshu.com/p/de8eb5eab167

  • 用户转到他们的配置文件页面。
  • 单击“启用双因素身份验证”。
  • 服务器生成秘密密钥,将其存储为用户配置文件的一部分,并将URL返回到QR代码。请注意,最好对秘密进行加密,以使数据泄露更加困难。
  • 用户使用Google身份验证应用程序扫描QR代码,从而在应用程序中创建新的配置文件
  • 用户在与qr代码一起出现的字段中输入应用程序的验证代码,然后单击“确认”。
  • 服务器将2FA标记为在用户配置文件中启用。
  • 或者,你可以给用户一些“抓取代码”,他们可以写下来,以防他们失去了自己的应用程序或秘密。
  • 如果用户不扫描代码或不验证进程,用户配置文件将只包含一个孤立的秘密密钥,但不会标记为已启用。
  • 应该有一个选项可以在以后从他们的用户配置文件页面中禁用2fa。

从理论上看,最重要的一点是密钥的共享。密码是对称的,所以双方(身份验证应用程序和服务器)都有相同的密钥。它通过用户扫描的QR代码共享。如果攻击者在这一点上控制了用户的计算机,那么这个秘密就可能被泄露,因此2FA也会被攻击者滥用。但这并不在威胁模型中--换句话说,如果攻击者能够访问用户的机器,那么破坏就已经发生了。

注意:您可能会看到这个过程称为2步认证或2因素。“因素”是:“你知道的东西”、“你拥有的东西”和“你是什么东西”。您可以将TOTP看作是“您知道”的另一件事,但您也可以使用安全存储的密钥将电话视为“您拥有”的东西。在这种情况下,我不坚持这两种术语。

登录时,流程如下:

https://www.douban.com/note/812706628/

  • 用户输入用户名和密码,然后单击“登录”。
  • 使用ajax请求,页面询问服务器这封电子邮件是否启用了2FA。
  • 如果未启用2FA,只需提交用户名和密码表单即可。
  • 如果启用了2fa,则不会提交登录表单,而是显示一个额外的字段,让用户从身份验证程序输入验证代码。
  • 在用户输入代码并按下登录后,可以提交表单。要么使用相同的登录按钮,要么使用新的“验证”按钮,或者验证输入+按钮可以是一个全新的屏幕(隐藏用户名/密码输入)。
  • 然后,服务器再次检查用户是否启用了2FA,如果有,则验证验证代码。如果匹配,登录就成功了。否则,登录失败,允许用户重新输入凭据和验证代码。请注意,根据用户名/密码是否错误或代码是否错误,您可以有不同的响应。您还可以尝试在显示验证代码输入之前登录。这种方法可以说是更好的,因为这样您就不会向潜在的攻击者透露用户使用2FA。

虽然我说的是用户名和密码,但这可以适用于任何其他身份验证方法。在从OAuth/OpenIDConnect/SAML提供程序获得成功确认后,或在您可以,您可以请求第二个因素(代码)。

在代码中,上面的流程如下(使用SpringMVC;为了简洁起见,我已经将控制器和服务层合并了。您可以用向控制器提供当前登录用户详细信息的方式替换@Authenticated主体位)。假设方法位于映射到“/user/”的控制器中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@RequestMapping(value = "/init2fa", method = RequestMethod.POST)
@ResponseBody
public String initTwoFactorAuth(@AuthenticationPrincipal LoginAuthenticationToken token) {
    User user = getLoggedInUser(token);
    GoogleAuthenticatorKey googleAuthenticatorKey = googleAuthenticator.createCredentials();
    // note - preferably encrypt it with an externally stored (or even HSM) key
    user.setTwoFactorAuthKey(googleAuthenticatorKey.getKey());
    dao.update(user);
    return GoogleAuthenticatorQRGenerator.getOtpAuthURL(GOOGLE_AUTH_ISSUER, email, googleAuthenticatorKey);
}
 
@RequestMapping(value = "/confirm2fa", method = RequestMethod.POST)
@ResponseBody
public boolean confirmTwoFactorAuth(@AuthenticationPrincipal LoginAuthenticationToken token, @RequestParam("code") int code) {
    User user = getLoggedInUser(token);
    boolean result = googleAuthenticator.authorize(user.getTwoFactorAuthKey(), code);
    user.setTwoFactorAuthEnabled(result);
    dao.update(user);
    return result;
}
 
@RequestMapping(value = "/disable2fa", method = RequestMethod.GET)
@ResponseBody
public void disableTwoFactorAuth(@AuthenticationPrincipal LoginAuthenticationToken token) {
    User user = getLoggedInUser(token);
    user.setTwoFactorAuthKey(null);
    user.setTwoFactorAuthEnabled(false);
    dao.update(user);
}
 
@RequestMapping(value = "/requires2fa", method = RequestMethod.POST)
@ResponseBody
public boolean login(@RequestParam("email") String email) {
    // TODO consider verifying the password here in order not to reveal that a given user uses 2FA
    return userService.getUserDetailsByEmail(email).isTwoFactorAuthEnabled();
}

QR代码生成使用的是Google的服务,从技术上讲,它也为Google提供了秘密密钥。我怀疑他们除了生成QR代码之外还存储它,但是如果您不信任它们,您可以实现您自己的QR代码生成你自己。

在客户端,对上述方法的Ajax请求很简单(sidenote:我觉得Ajax这个术语不再流行,但我不知道如何称呼它们。异步?背景?JavaScript?)。

https://www.imdb.com/list/ls503156708/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$("#two-fa-init").click(function() {
    $.post("/user/init2fa", function(qrImage) {
    $("#two-fa-verification").show();
    $("#two-fa-qr").prepend($('<img>',{id:'qr',src:qrImage}));
    $("#two-fa-init").hide();
    });
});
 
$("#two-fa-confirm").click(function() {
    var verificationCode = $("#verificationCode").val().replace(/ /g,'')
    $.post("/user/confirm2fa?code=" + verificationCode, function() {
       $("#two-fa-verification").hide();
       $("#two-fa-qr").hide();
       $.notify("Successfully enabled two-factor authentication", "success");
       $("#two-fa-message").html("Successfully enabled");
    });
});
 
$("#two-fa-disable").click(function() {
    $.post("/user/disable2fa", function(qrImage) {
       window.location.reload();
    });
});

登录表单代码在很大程度上取决于您正在使用的现有登录表单,但重点是使用电子邮件(和密码)调用/requres2fa来检查是否启用了2FA,然后显示一个验证代码输入。

总的来说,如果双因素身份验证很简单的话,那么实现就更简单了,我建议在大多数系统中,安全性比用户体验的简单性更重要。

原文地址:https://www.cnblogs.com/aiqiyi/p/15271975.html