如何对安全密码执行验证。 char[] 上的正则表达式?

Posted

技术标签:

【中文标题】如何对安全密码执行验证。 char[] 上的正则表达式?【英文标题】:How can I perform validation on a secure password. Regular expressions on a char[]? 【发布时间】:2014-09-15 10:54:05 【问题描述】:

这个问题是对这里问题的跟进:

Why is char[] preferred over String for passwords?

这个问题非常有助于理解为什么使用 char[] 而不是 String;但是,它没有解释如何以安全的方式对 char[] 执行密码验证。这就是我想在这里了解的。

简单来说,我需要检查密码是否满足以下要求:

至少包含一个大写字母 至少包含一个小写字母 至少包含一位数字 至少包含一个符号 至少为 n 个字符,但不超过 m

现在我明白了如何使用正则表达式来执行验证......这些答案显示了如何做到这一点:

Regexp Java for password validation Password must be 8 characters including 1 uppercase letter, 1 special character, alphanumeric characters

据我所知,正则表达式检查涉及使用字符串。使用它们似乎并不安全,因为字符串是不可变的,因此在使用它们后无法立即清除它们。另一方面,可以清除 char[]。

那么,如何对存储在 char[] 而不是字符串中的密码进行验证?

我可以遍历每个字符,但是我必须创建每个我想测试的集合。理想情况下,能够利用正则表达式会很有用。

在Java中,我可以通过以下方法进行正则表达式检查。

String.matches(String regex)

或者

Pattern pattern = Pattern.compile(String regex);
pattern.matcher(CharSequence testString).matches();

如您所见,这两种方法都不支持直接使用 char[]。

【问题讨论】:

没有这样做的经验,所以我不知道安全后果,但是,您可以编译自己的 Pattern 并使用 matcher(CharSequence) 【参考方案1】:

我会尽量避免使用复杂的正则表达式,我会建议类似 -

boolean validatePassword(char[] password, int n, int m) 
  if (password == null || password.length < n || password.length > m) 
    return false;
  
  boolean upper = false;
  boolean lower = false;
  boolean digit = false;
  boolean symbol = false;
  for (char ch : password) 
    if (Character.isUpperCase(ch)) 
      upper = true;
     else if (Character.isLowerCase(ch)) 
      lower = true;
     else if (Character.isDigit(ch)) 
      digit = true;
     else  // or some symbol test.
      symbol = true;
    
    // This short-circuits the rest of the loop when all criteria are true.
    if (upper && lower && digit && symbol) 
      return true;
    
  
  return upper && lower && digit && symbol;

【讨论】:

谢谢!虽然这不使用正则表达式,但它仍然进行验证。我不知道Character.isLower/Upper/Digit() 功能。如果目标是清除密码,不应该将本地 char[] 清零吗? @NickMiller 一般来说,我宁愿让调用者处理它。一旦此方法完成,您就知道密码仅作为密码有效(本身不是正确的密码),您实际上还没有对它进行任何操作(据此方法所知)。 如果我错了请纠正我,但是方法中的char []不是副本吗?而如果是副本,就应该清除掉,因为我们不想等到 GC 激活。 @NickMiller 好消息!你不正确。它不是副本。 Java 是按值传递,但 Object(s) 的值,包括 Array(s),是引用。 啊!我明白了,引用被复制了,但是两个引用都指向同一个内存! :)【参考方案2】:

只需遍历char[] 即可进行基本的密码接受验证

【讨论】:

【参考方案3】:

您可以使用CharBuffer.wrap(char[])CharSequence 的形式访问char 数组。

Pattern.matches(regex, CharBuffer.wrap(myCharArray))

【讨论】:

【参考方案4】:

Java 的正则表达式实现不需要 String 对象 - 您应该传递 CharSequence。如果您不想从char[] 数组创建String,您可以将数组包装在您自己的CharSequence 接口实现中。

【讨论】:

我喜欢这个,因为CharSequence 可以在后台包含一个可变的char[]。我可以限制访问并提供一个函数来在我完成后清除数组。我唯一关心的是正则表达式函数是否存储字符数据。

以上是关于如何对安全密码执行验证。 char[] 上的正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式验证密码强度

正则表达式验证密码强度

无法对 Azure 上的 API 管理执行资源所有者密码 OAuth2 身份验证

通过 SOAP 服务向 JIRA 进行身份验证时安全密码存储

如何使用 Angular 5 验证器模式验证密码强度

使用正则表达式提高用户密码的复杂度和安全性