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

Java 如何对安全密码执行验证。字符[]上的正则表达式?,java,regex,validation,passwords,arrays,Java,Regex,Validation,Passwords,Arrays,此问题是以下问题的后续问题: 这个问题非常有助于理解为什么使用char[]而不是字符串是好的;但是,它没有解释如何以安全的方式对char[]执行密码验证。这就是我想知道的 简单地说,我需要检查密码是否满足以下要求: 至少包含一个大写字母 至少包含一个小写字母 包含至少一个数字 包含至少一个符号 至少为n个字符,但不超过m个字符 现在我了解了如何使用正则表达式执行验证。。。这些答案说明了如何做到这一点: 据我所知,正则表达式检查涉及使用字符串。使用它们似乎不安全,因为字符串是不可变的

此问题是以下问题的后续问题:

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

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

  • 至少包含一个大写字母
  • 至少包含一个小写字母
  • 包含至少一个数字
  • 包含至少一个符号
  • 至少为n个字符,但不超过m个字符
现在我了解了如何使用正则表达式执行验证。。。这些答案说明了如何做到这一点:

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

那么,如何对存储在char[]中而不是字符串中的密码执行验证呢? 我可以遍历每个字符,但接下来我必须创建要测试的每个集合。理想情况下,能够利用正则表达式会很有用

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

String.matches(String regex)


正如您所看到的,这两种方法都不支持直接使用char[].

只需迭代
char[]
即可执行基本的密码接受验证

Java的regex实现不需要
String
对象-您需要传递一个密码。如果您不想从
char[]
数组创建
String
,您可以在自己的
CharSequence
接口实现中包装一个数组。

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

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;
}
布尔验证密码(char[]密码,int n,int m){
if(password==null | | password.lengthm){
返回false;
}
布尔上限=假;
布尔下限=假;
布尔数字=假;
布尔符号=假;
for(字符:密码){
if(字符.isUpperCase(ch)){
上限=真;
}else if(字符.isLowerCase(ch)){
较低=正确;
}else if(字符isDigit(ch)){
数字=真;
}else{//或一些符号测试。
符号=真;
}
//当所有条件均为真时,这会使循环的其余部分短路。
if(上、下、数字和符号){
返回true;
}
}
返回上、下、数字和符号;
}
您可以使用以
字符序列的形式访问字符数组

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

没有这样做的经验,所以我不知道安全性的后果,但是,您可以编译自己的
模式
并使用
matcher(CharSequence)
我喜欢这样,因为
CharSequence
可以在后台包含可变的
char[]
。我可以限制访问,并提供一个函数在完成后清除阵列。我唯一关心的是正则表达式函数是否存储字符数据。谢谢!虽然它不使用正则表达式,但它仍然进行验证。我不知道
Character.isLower/Upper/Digit()。如果目标是删除密码,本地字符[]是否应该归零?@NickMiller通常,我更愿意让调用方处理它。此方法完成后,您知道密码仅作为密码(不是正确的密码本身)有效,但实际上您尚未对其执行任何操作(就此方法所知)。如果我错了,请更正我,但方法中的字符[]不是副本吗?如果它是一个副本,它应该被清除,因为我们不想等到GC激活。@NickMiller好消息!你错了。它不是复制品。Java是按值传递的,但对象(包括数组)的值是引用。啊!我明白了,引用被复制了,但两个引用指向相同的内存!:)
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;
}