为什么 char[] 优于 String 的密码?
问:
在 Swing 中,密码字段有一个 getPassword()(返回 char[])方法,而不是通常的 getText()(返回 String)方法。同样,我遇到了一个建议,不要使用 String 来处理密码。
为什么在密码方面 String 会对安全构成威胁?使用char[]感觉不方便。
答1:
huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感
字符串是不可变的。这意味着一旦您创建了 String,如果另一个进程可以转储内存,那么(除了 reflection)您将无法在 garbage collection 启动之前删除数据。
使用数组,您可以在完成后显式擦除数据。你可以用你喜欢的任何东西覆盖数组,密码不会出现在系统的任何地方,甚至在垃圾收集之前。
所以是的,这是一个安全问题 - 但即使使用 char[] 也只会减少攻击者的机会之窗,而且它仅适用于这种特定类型的攻击。
如评论中所述,垃圾收集器移动的数组可能会将数据的杂散副本留在内存中。我相信这是特定于实现的 - 垃圾收集器可能清除所有内存,以避免这种事情。即使是这样,仍有一段时间 char[] 包含实际字符作为攻击窗口。
如果一个进程可以访问您的应用程序的内存,那么这已经是一个安全漏洞,对吧?
@Yeti:是的,但它不像是黑白的。如果他们只能获取内存的快照,那么您希望减少快照可以造成的损害,或者减少可以拍摄非常严重的快照的窗口。
一种常见的攻击方法是运行一个分配大量内存的进程,然后扫描它以查找剩余的有用数据,例如密码。该进程不需要对另一个进程的内存空间进行任何神奇的访问;它只是依赖于其他进程在没有首先清除敏感数据的情况下死亡,并且操作系统在使其可用于新进程之前也不会清除内存(或页面缓冲区)。清除存储在 char[] 位置的密码会切断该攻击线,而使用 String 则无法做到这一点。
如果操作系统在将内存交给另一个进程之前没有清除内存,则操作系统存在重大安全问题!然而,从技术上讲,清除通常是通过保护模式技巧完成的,如果 CPU 坏了(例如 Intel Meldown),仍然可以读取旧的内存内容。
@PrateekPande:只有在源代码中存在或显式实习时,它才会出现在文字池中。总的来说,这两个都是坏主意……
答2:
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求
虽然这里的其他建议似乎有效,但还有一个很好的理由。使用普通的 String,您不小心将密码打印到日志、监视器或其他一些不安全的地方的几率要高得多。 char[] 不太容易受到攻击。
考虑一下:
public static void main(String[] args) {Object pw = "Password";System.out.println("String: " + pw);pw = "Password".toCharArray();System.out.println("Array: " + pw);
}
印刷:
String: Password
Array: [C@5829428e
@voo,但我怀疑您是否会通过直接写入流和连接来登录。日志框架会将 char[] 转换为良好的输出
@Thr4wn toString 的默认实现是 classname@hashcode。 [C代表char[],其余为十六进制哈希码。
有趣的想法。我想指出,这不会转置为对数组具有有意义的 toString 的 Scala。
我会为此编写一个 Password 类类型。它不那么晦涩难懂,也更难意外通过某个地方。
为什么有人会假设 char 数组将被转换为对象?我不确定我明白为什么每个人都喜欢这个答案。假设你这样做了: System.out.println("Password".toCharArray());
答3:
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求
引用官方文档,Java Cryptography Architecture guide 是关于 char[] 与 String 密码(关于基于密码的加密,但这当然更普遍地与密码有关):
将密码收集并存储在 java.lang.String 类型的对象中似乎是合乎逻辑的。但是,需要注意的是:String 类型的对象是不可变的,即没有定义允许您在使用后更改(覆盖)或清零 String 内容的方法。此功能使 String 对象不适合存储用户密码等安全敏感信息。您应该始终将安全敏感信息收集并存储在 char 数组中。
Guideline 2-2 of the Secure Coding Guidelines for the Java Programming Language, Version 4.0 也说了类似的话(尽管它最初是在日志记录的上下文中):
准则 2-2:不要记录高度敏感的信息 一些信息,例如社会安全号码 (SSN) 和密码,是高度敏感的。此信息不应保存超过必要的时间,也不应保存在可能被管理员看到的地方。例如,不应将其发送到日志文件,并且不应通过搜索检测到其存在。一些瞬态数据可能保存在可变数据结构中,例如 char 数组,并在使用后立即清除。清除数据结构在典型的 Java 运行时系统上降低了效率,因为对象在内存中对程序员透明地移动。该指南还对不具备所处理数据的语义知识的低级库的实现和使用产生影响。例如,低级字符串解析库可能会记录它处理的文本。应用程序可以使用库解析 SSN。这会产生一种情况,即 SSN 可供有权访问日志文件的管理员使用。
这正是我在乔恩的回答下面谈到的有缺陷/虚假的参考资料,这是一个众所周知的来源,有很多批评。
@bestass你能不能也引用一个参考?
@bestass 很抱歉,但是 String 很好理解,它在 JVM 中的行为方式......在以安全方式处理密码时,有充分的理由使用 char[] 代替 String。
尽管密码作为字符串从浏览器传递给请求,但又是“字符串”而不是字符?所以无论你做什么,它都是一个字符串,此时它应该被处理并丢弃,而不是存储在内存中?
@Dawesi - At which point - 这是特定于应用程序的,但一般规则是一旦你拿到应该是密码的东西(明文或其他)就这样做。例如,您可以从浏览器获取它作为 HTTP 请求的一部分。你无法控制投递,但你可以控制自己的存储,所以一拿到它,就把它放在一个 char[] 中,用它做你需要做的事情,然后将所有设置为 '0' 并让 gc收回它。
答4:
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
字符数组 (char[]) 可以在使用后通过将每个字符设置为零而不是字符串来清除。如果有人能以某种方式看到内存映像,如果使用字符串,他们可以看到纯文本密码,但如果使用 char[],在用 0 清除数据后,密码是安全的。
默认情况下不安全。如果我们谈论的是 Web 应用程序,大多数 Web 容器都会将密码以明文形式传递给 HttpServletRequest 对象。如果 JVM 版本是 1.6 或更低,它将在 permgen 空间中。如果它在 1.7 中,它在被收集之前仍然是可读的。 (无论何时。)
@avgvstvs:字符串不会自动移动到 permgen 空间,这只适用于实习字符串。除此之外,permgen 空间也受到垃圾收集的影响,只是速度较低。 permgen 空间的真正问题在于它的固定大小,这正是没有人应该在任意字符串上盲目调用 intern() 的原因。但是您是对的,因为 String 实例首先存在(直到收集),然后将它们转换为 char[] 数组并不会改变它。
@Holger 请参阅docs.oracle.com/javase/specs/jvms/se6/html/…“否则,将创建一个 String 类的新实例,其中包含 CONSTANT_String_info 结构给出的 Unicode 字符序列;该类实例是字符串文字推导的结果。最后,新 String 实例的 intern 方法被调用。”在 1.6 中,当 JVM 检测到相同的序列时,它会为您调用 intern。
@Holger,你是对的,我将常量池和字符串池混为一谈,但是 permgen 空间 only 应用于实习字符串也是错误的。在 1.7 之前,constant_pool 和 string_pool 都驻留在 permgen 空间中。这意味着分配给堆的唯一字符串类是如您所说的 new String() 或 StringBuilder.toString() 我管理具有大量字符串常量的应用程序,因此我们有很多 permgen crawl。直到 1.7。
@avgvstvs:嗯,字符串常量,按照 JLS 的要求,总是被实习的,因此实习字符串最终在 permgen 空间中的语句,隐式应用于字符串常量。唯一的区别是字符串常量首先是在 permgen 空间中创建的,而对任意字符串调用 intern() 可能会导致在 permgen 空间中分配等效字符串。如果没有共享该对象的相同内容的文字字符串,则后者可能会被 GC 处理……
答5:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
有些人认为,一旦不再需要密码,就必须覆盖用于存储密码的内存。这减少了攻击者必须从您的系统读取密码的时间窗口,并且完全忽略了攻击者已经需要足够的访问权限来劫持 JVM 内存来执行此操作的事实。具有如此多访问权限的攻击者可以捕获您的关键事件,从而使其完全无用(AFAIK,如果我错了,请纠正我)。
更新
感谢评论,我必须更新我的答案。显然,在两种情况下,这可以增加(非常)小的安全性改进,因为它减少了密码可能落在硬盘上的时间。我仍然认为对于大多数用例来说这太过分了。
您的目标系统可能配置错误,或者您必须假设它是,并且您必须对核心转储持偏执态度(如果系统不是由管理员管理,则可能有效)。
您的软件必须过于偏执,以防止攻击者获得对硬件的访问权限而导致数据泄露——使用诸如 TrueCrypt(已停产)、VeraCrypt 或 CipherShed 之类的东西。
如果可能,禁用核心转储和交换文件将解决这两个问题。但是,它们需要管理员权限,并且可能会减少功能(使用更少的内存)并且从正在运行的系统中提取 RAM 仍然是一个有效的问题。
我会用“只是轻微的安全改进”来代替“完全没用”。例如,如果您碰巧拥有对 tmp 目录的读取权限、一台配置错误的机器以及您的应用程序崩溃,那么您就可以访问内存转储。在这种情况下,您将无法安装键盘记录器,但您可以分析核心转储。
完成后立即从内存中擦除未加密的数据被认为是最佳实践,而不是因为它是万无一失的(它不是);但因为它降低了你的威胁暴露水平。这样做并不能防止实时攻击;但是因为它通过显着减少在对内存快照的追溯攻击中暴露的数据量(例如,写入交换文件或从内存中读取的应用程序内存的副本)来提供损害缓解工具从正在运行的服务器并在其状态失败之前移动到另一个服务器)。
我倾向于同意这种回应的态度。我冒昧地提出,大多数安全漏洞的后果都发生在比内存中的位更高的抽象级别上。当然,在超安全防御系统中可能存在一些场景,这可能会引起相当大的关注,但在这个级别上认真考虑对于 99% 正在利用 .NET 或 Java 的应用程序来说是多余的(因为它与垃圾收集有关)。
在 Heartbleed 穿透服务器内存并泄露密码之后,我会将字符串“只是一个小的安全改进”替换为“绝对不能使用字符串作为密码,而是使用 char []。”
@PetervdL heartbleed 仅允许读取特定的重用缓冲区集合(用于安全关键数据和网络 I/O,而不会在两者之间清除 - 出于性能原因),您不能将其与 Java 字符串结合使用,因为它们在设计上不可重用.您也不能使用 Java 读入随机内存来获取字符串的内容。导致心脏出血的语言和设计问题对于 Java 字符串是不可能的。
答6:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
我不认为这是一个有效的建议,但是,我至少可以猜到原因。
我认为动机是希望确保您可以在使用后立即并确定地清除内存中的所有密码痕迹。使用 char[],您可以肯定地用空白或其他内容覆盖数组的每个元素。您不能以这种方式编辑 String 的内部值。
但这并不是一个好的答案。为什么不只是确保对 char[] 或 String 的引用不会逃逸?那么就没有安全问题了。但问题是 String 对象在理论上可以intern() 编辑并在常量池中保持活动状态。我想使用 char[] 禁止这种可能性。
我不会说问题在于您的参考文献会或不会“逃脱”。只是字符串会在内存中保持一段时间不被修改,而 char[] 可以修改,然后它是否被收集无关紧要。而且由于需要为非文字显式地完成字符串实习,这就像告诉静态字段可以引用 char[] 一样。
内存中的密码不是作为表单帖子中的字符串吗?
答7:
huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式
答案已经给出,但我想分享一个我最近在 Java 标准库中发现的问题。虽然他们现在非常注意用 char[] 替换密码字符串(这当然是一件好事),但在从内存中清除其他安全关键数据时似乎被忽略了。
我正在考虑例如 PrivateKey 类。考虑一个场景,您将从 PKCS#12 文件加载私有 RSA 密钥,并使用它来执行某些操作。现在在这种情况下,只要适当限制对密钥文件的物理访问,单独嗅探密码对您没有多大帮助。作为攻击者,如果您直接获得密钥而不是密码,您的情况会好得多。所需的信息可以是多种泄漏、核心转储、调试器会话或交换文件只是一些示例。
事实证明,没有什么可以让您从内存中清除 PrivateKey 的私有信息,因为没有 API 可以让您擦除形成相应信息的字节。
这是一个糟糕的情况,因为此 paper 描述了如何可能利用这种情况。
例如,OpenSSL 库会在释放私钥之前覆盖关键内存部分。由于 Java 是垃圾收集的,因此我们需要明确的方法来擦除和无效 Java 密钥的私有信息,这些信息将在使用密钥后立即应用。
解决此问题的一种方法是使用 PrivateKey 的实现,它实际上不会将其私有内容加载到内存中:例如,通过 PKCS#11 硬件令牌。也许 PKCS#11 的软件实现可以手动清理内存。也许使用类似 NSS 存储(它与 Java 中的 PKCS11 存储类型共享其大部分实现)之类的东西会更好。 KeychainStore(OSX 密钥库)将私钥的全部内容加载到其 PrivateKey 实例中,但它不需要这样做。 (不确定 WINDOWS-MY KeyStore 在 Windows 上的作用。)
@Bruno 当然,基于硬件的令牌不会受到此影响,但是在您或多或少被迫使用软件密钥的情况下呢?并非每个部署都有预算来负担 HSM。软件密钥存储在某些时候必须将密钥加载到内存中,因此 IMO 我们至少应该可以选择再次随意清除内存。
当然,我只是想知道某些与 HSM 等效的软件实现在清理内存方面是否表现得更好。例如,当在 Safari/OSX 中使用 client-auth 时,Safari 进程实际上永远不会看到私钥,操作系统提供的底层 SSL 库直接与提示用户使用钥匙串中的密钥的安全守护进程对话。虽然这一切都是在软件中完成的,但如果将签名委托给可以更好地卸载或清除内存的不同实体(甚至是基于软件的),类似这样的分离可能会有所帮助。
@Bruno:有趣的想法,一个额外的负责清除内存的间接层确实可以透明地解决这个问题。为软件密钥库编写一个 PKCS#11 包装器已经可以解决问题了吗?
有趣的是,您应该说他们非常注意“现在”使用 char[],因为我正在查看 JDK 9 中添加的这个不错的新 ConnectionBuilder 类,它仍然有 password(String) 并且没有通过 {1 的选项}。似乎使用 Java 有很多“做我说的,而不是我做的”。
答8:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
正如 Jon Skeet 所说,除了使用反射之外别无他法。
但是,如果反射是您的选择,您可以这样做。
public static void main(String[] args) {System.out.println("please enter a password");// don't actually do this, this is an example only.Scanner in = new Scanner(System.in);String password = in.nextLine();usePassword(password);clearString(password);System.out.println("password: '" + password + "'");
}private static void usePassword(String password) {}private static void clearString(String password) {try {Field value = String.class.getDeclaredField("value");value.setAccessible(true);char[] chars = (char[]) value.get(password);Arrays.fill(chars, '*');} catch (Exception e) {throw new AssertionError(e);}
}
运行时
please enter a password
hello world
password: '***********'
注意:如果字符串的 char[] 已作为 GC 循环的一部分被复制,则前一个副本有可能在内存中的某个位置。
这个旧副本不会出现在堆转储中,但如果您可以直接访问进程的原始内存,您可以看到它。一般来说,您应该避免任何拥有此类访问权限的人。
最好也采取一些措施来防止打印我们从 '***********' 获得的密码长度。
@chux,您可以使用零宽度字符,尽管这可能比有用更令人困惑。不使用 Unsafe 就无法更改 char 数组的长度。 ;)
由于 Java 8 的字符串重复数据删除,我认为这样做可能会非常具有破坏性……您最终可能会清除程序中偶然具有与密码字符串相同的值的其他字符串。不太可能,但可能...
@PeterLawrey 必须使用 JVM 参数启用它,但它就在那里。可以在这里阅读:blog.codecentric.de/en/2014/08/…
密码很有可能仍然在 Scanner 的内部缓冲区中,并且由于您没有使用 System.console().readPassword(),因此在控制台窗口中以可读的形式存在。但对于大多数实际用例,usePassword 的执行持续时间是实际问题。例如,当与另一台机器建立连接时,它会花费大量时间并告诉攻击者现在是在堆中搜索密码的正确时间。唯一的解决方案是防止攻击者读取堆内存……
答9:
huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。
这些都是原因,应该选择 char[] 数组而不是 String 作为密码。
- 由于字符串在 Java 中是不可变的,如果您将密码存储为纯文本,它将在内存中可用,直到垃圾收集器清除它,并且由于字符串在字符串池中用于可重用性,所以它很有可能会长时间保留在内存中,这构成了安全威胁。
由于任何有权访问内存转储的人都可以找到明文密码,这就是您应该始终使用加密密码而不是纯文本的另一个原因。由于字符串是不可变的,因此无法更改字符串的内容,因为任何更改都会产生新的字符串,而如果您使用 char[],您仍然可以将所有元素设置为空白或零。因此,将密码存储在字符数组中显然可以降低窃取密码的安全风险。
-
Java 本身建议使用 JPasswordField 的 getPassword() 方法,它返回一个 char[],而不是已弃用的 getText() 方法,它以明文形式返回说明安全原因的密码。遵循 Java 团队的建议并遵守标准而不是违背标准是很好的。
-
使用 String 总是存在在日志文件或控制台中打印纯文本的风险,但是如果您使用数组,您将不会打印数组的内容,而是打印其内存位置。虽然不是真正的原因,但它仍然是有道理的。
String strPassword="Unknown";
char[] charPassword= new char[]{'U','n','k','w','o','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);String password: Unknown
Character password: [C@110b053
引用自 this blog。我希望这有帮助。
这是多余的。这个答案是@SrujanKumarGulla stackoverflow.com/a/14060804/1793718 所写答案的精确版本。请不要复制粘贴或重复相同的答案两次。
1.) System.out.println("字符密码:" + charPassword); 有什么区别2.) System.out.println(charPassword);因为它给出了与输出相同的“未知”。
@Lucky不幸的是,您链接到的旧答案是从与此答案相同的博客中剽窃的,现在已被删除。请参阅meta.stackoverflow.com/questions/389144/…。这个答案只是从同一个博客中剪切和粘贴,没有添加任何内容,所以它应该只是一个链接到原始来源的评论。
“由于字符串在字符串池中用于可重用性,它很有可能会在内存中保留很长时间,这会带来安全威胁。”仅当您显式调用了 intern() 或者它是文字字符串时,字符串才会出现在字符串池中。无论如何,用户密码不能是文字字符串,并且不鼓励使用 intern() 方法,尽管字符串是密码。
答10:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
编辑: 在经过一年的安全研究后回到这个答案,我意识到这意味着您实际上会比较明文密码,这是相当不幸的暗示。请不要。 Use a secure one-way hash with a salt and a reasonable number of iterations。考虑使用库:这些东西很难做对!
原始答案: String.equals() 使用 short-circuit evaluation 并因此容易受到计时攻击这一事实又如何呢?这可能不太可能,但您可以理论上对密码比较进行计时,以确定正确的字符序列。
public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;// Quits here if Strings are different lengths.if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;// Quits here at first different character.while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}
有关定时攻击的更多资源:
定时攻击的教训
关于信息安全堆栈交换上的定时攻击的讨论
当然,Timing Attack Wikipedia 页面
但这也可能存在于 char[] 比较中,在某个地方我们也会在密码验证中做同样的事情。那么 char[] 怎么比字符串好呢?
你是绝对正确的,无论哪种方式都可能犯错误。了解问题是这里最重要的事情,考虑到 Java 中没有针对基于字符串或基于 char[] 的密码的显式密码比较方法。我想说对字符串使用 compare() 的诱惑是使用 char[] 的一个很好的理由。这样,您至少可以控制比较的完成方式(无需扩展 String,这在 imo 中很痛苦)。
除了比较明文密码无论如何都不是正确的事情之外,将 Arrays.equals 用于 char[] 的诱惑与 String.equals 一样高。如果有人关心的话,这里有一个专门的密钥类来封装实际密码并处理问题——哦等等,真正的安全包有专门的密钥类,这个问答只是关于一个习惯 在它们之外,例如 JPasswordField,使用 char[] 而不是 String(实际算法无论如何都使用 byte[])。
安全相关软件在拒绝登录尝试之前应该执行类似 sleep(secureRandom.nextInt()) 的操作,这不仅消除了定时攻击的可能性,还可以抵消暴力尝试。
答11:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
除非您在使用后手动清理它,否则 char 数组不会为您提供与 String 相比的任何东西,而且我还没有看到有人真正这样做。所以对我来说 char[] vs String 的偏好有点夸张。
看看广泛使用 Spring Security 库here,问问自己 - Spring Security 的人是无能的还是 char[] 密码没有多大意义。当一些讨厌的黑客窃取您 RAM 的内存转储时,即使您使用复杂的方法来隐藏它们,请确保他/她会获得所有密码。
然而,Java 一直在变化,一些可怕的特性(如 String Deduplication feature of Java 8)可能会在您不知情的情况下实习 String 对象。但这是一个不同的对话。
为什么字符串重复数据删除很可怕?它仅适用于至少有两个具有相同内容的字符串,那么让这两个已经相同的字符串共享同一个数组会产生什么危险呢?或者让我们反过来问:如果没有字符串重复数据删除,那么两个字符串都有一个不同的数组(具有相同的内容)这一事实会产生什么优势?在任何一种情况下,至少只要该内容中最长的存活字符串还活着,就会有一个该内容的数组是活着的……
@Holger 任何你无法控制的事情都是潜在的风险......例如,如果两个用户有相同的密码,这个奇妙的功能会将他们两个都存储在单个 char[] 中,从而很明显它们是相同的,不确定那是不是巨大的风险,但仍然
如果您可以访问堆内存和两个字符串实例,那么字符串是指向同一个数组还是指向两个具有相同内容的数组都没有关系,每个都很容易找到。特别是,因为无论如何它都无关紧要。如果你在这一点上,你抓住两个密码,无论是否相同。实际的错误在于使用明文密码而不是加盐哈希。
@Holger 验证密码它必须在内存中以明文形式存在一段时间,10 毫秒,即使它只是为了从中创建一个加盐哈希。然后,如果碰巧有两个相同的密码在内存中保存了 10 毫秒,那么重复数据删除可能会发挥作用。如果它真的实习字符串,它们会在内存中保存更长的时间。几个月不重启的系统会收集很多这些。只是理论。
看来,您对字符串重复数据删除存在根本性的误解。它不是“实习字符串”,它所做的只是让具有相同内容的字符串指向同一个数组,这实际上减少了包含明文密码的数组实例的数量,因为除了一个数组实例之外的所有数组实例都可以被回收和覆盖立即被其他物体。这些字符串仍然像任何其他字符串一样被收集。如果您了解重复数据删除实际上是由垃圾收集器完成的,那么它可能会有所帮助,对于仅在多个 GC 周期中幸存下来的字符串。
原文链接:https://www.huntsbot.com/qa/Pdrb/why-is-char-preferred-over-string-for-passwords?lang=zh_CN&from=csdn
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/299946.html
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!相关文章:

为什么 char[] 优于 String 的密码?
问: 在 Swing 中,密码字段有一个 getPassword()(返回 char[])方法,而不是通常的 getText()(返回 String)方法。同样,我遇到了一个建议,不要使用 String 来处理密码。 为…...

如何识别网络应用层协议?
能够标识出 Internet上每个流所使用的应用层协议是一系列网络应用的前提和基础。然而随着网络的高速化和协议的复杂化,传统的基于端 口识别应用层协议的算法已经不够准确,因此各种新的协议识别算法成为研究热点 。 本篇文章将重点介绍协议识别问题的几个…...

skynet的actor对等调度分析
skynet的actor对等调度一、actor对等调度二、调度流程源码分析2.1、thread_worker()2.2、struct skynet_context2.3、skynet_context_message_dispatch()2.4、dispatch_message()三、c语言到lua的调用过程分析总结后言一、actor对等调度 actor的调度由线程池来调度。actor是被…...

01背包问题以及有关题目
一、01背包问题详解 确定dp数组以及下标的含义 使用二维数组 dp[i] [j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。 确定递推公式 dp数组的初始化 首先从dp[i][j] 的定义出发,如果背包容量j为0的话&#…...

SSM 学习管理系统
SSM 学习管理系统 SSM 学习管理系统 功能介绍 首页 图片轮播展示 网站公告 学生注册 教师注册 课程资料 视频学习 友情链接 资料详情 学习进度 评论 收藏 后台管理 登录 管理员管理 修改密码 网站公告管理 友情链接管理 轮播图管理 学生管理 班级管理 我的班级管理 教师管理…...

前端按钮/组件权限管理
最近项目中遇到了按钮权限管理的需求,整理了一下目前的方案,有不对的地方望大家指出~ 方案1:数组自定义指令 把权限放到数组中,通过vue的自定义指令来判断是否拥有该权限,有则显示,反之则不显…...

[JavaScript]使用opencv.js实现基于傅里叶变换的频域水印(隐水印)
PS:查了多方资料,都没有提到用 JavaScript 来实现频域水印的教程,故经过笔者的实践,遂写一篇教程来简单介绍。 通过了解频域水印的相关知识,我理解了频域水印就是先将图片进行傅里叶变换,得到频域图&#x…...

P3916 图的遍历——反向建边dfs
图的遍历 题目描述 给出 NNN 个点,MMM 条边的有向图,对于每个点 vvv,求 A(v)A(v)A(v) 表示从点 vvv 出发,能到达的编号最大的点。 输入格式 第 111 行 222 个整数 N,MN,MN,M,表示点数和边数。 接下来 MMM 行&…...

vpp hash源码分析
概述 vpp的hash结构分为hash头、桶(_hash_create或hash_resize申请)和桶下元素(clib_mem_realloc申请),总共3个部分组成。 根据元素key的hash值不同,分配到不同的桶下,与其他hash表原理相同。 …...

Linux系统部署
Linux系统部署 下载vmware centos7 xshell6 xftp6新建虚拟机,注意设置网络连接,设置登录名:root,密码:root,等待登录,输入用户名和密码(注意密码输入不显示)登录成功,执行命令Ifc…...

Java中的默认值和构造器
默认值: 数据类型的默认值为0; boolean的默认为false; 对象类型的默认值为null。 但在写程序的时候,一定要手动给个值,不然在后期容易出错。 构造器: 如果不手动写构造器,程序在编译的时候…...

构造器的用法
关于构造器: 还有this的用法 还有个地方要注意,像下面的代码中,构造器2中调用构造器1的语句,必须放在构造器2的第一句。必须!!! public class Main {private String name;private double sal…...

关于类继承中子类方法比父类方法丰富,一个引用值传递的小问题
对于前两个程序,一个父类一个子类,我们如果这样: public class ForTest {public static void main(String[] args) {// TODO Auto-generated method stubEmployee e1new Employee("小张",9800,1998,2,14);Employee e2new Employee…...

ArrayList和变参
其实没什么好说的,只是写下来作个备忘录 1.ArrayList的声明和实例化 import java.util.ArrayList; …… ArrayList<String> strnew ArrayList<>(99);//写法1 ArrayList<String> str1new ArrayList<String>();//写法2 其拥有add(Object o)…...

反射机制知识点(new和newInstance之区别)
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此…...

Java反射机制--肤浅认知
本来不是很懂,看了很多文章解析,感觉貌似有点懂了。 记下备忘。待后来回头查看,以便更正。 Java反射机制是:在程序编译以后,运行过程中,实时获取新的类名,并且可以获知新类的方法、域和构造器…...

Java反射机制--佐证
这个例子很好的证明了,类加载和实例化的区别: public class NewInstancesTest {public static void main(String[] args) {TestOne onenull;try {//类加载Class clClass.forName("reflectTest.TestOne");//引号内的作用,是指定要加…...

定时器与回调
测试类 import java.awt.event.ActionListener; import javax.swing.JOptionPane; import javax.swing.Timer;public class Test {public static void main(String[] args) {ActionListener listennew TimeToPrint();Timer tnew Timer(10,listen);t.start();JOptionPane.showM…...

内部类、异常、断言和Loger日志
以后补充...

泛型的简单写法
在写程序的时候,有时候没办法必须用一个泛型的类或者方法,提前学到这个写法,对以后应该会很有好处。 public class PairTest1 {public static void main(String[] args){String [] temString{"a","c","e",&qu…...