分类 默认分类 下的文章

引入

当在12306上查车次时,例如输入北京-上海时,返回的结果里车次往往会有出发站点是北京南,到达站点里也会有上海虹桥,这里可能会让人觉得12306查车次可以按城市查询,但是12306查车次时并不支持城市,12306或者其他二方三方渠道里都是按照车站来查询车次的。因此在车次查询过程中,针对一些车站,在查询时会顺带返回同城市的其他车站的车次结果。

- 阅读剩余部分 -

本文谈论的clean code要求并不高(常规水平),我觉得对于日常开发来说能达到:

  • 变量命名清晰简洁、
  • 函数功能较为单一,逻辑清晰,能复用的情况下做到不同函数职责设计合理
  • 简单场景能简单用到常用设计模式
  • ...

以上这些能做到,写出的代码就已经算得上是中上水平了(不要求用一些高阶方法或者什么巧妙方法,甚至没有完整看过代码整洁之道或者重构这种书籍也可以,能正常写整洁代码就可以了),对此有的公司可能要求会更高。

类似于写字,不要求每个人都能写出非常漂亮的字,至少看起来要工整这个要求并不过分。

- 阅读剩余部分 -

为什么推荐优先使用char[]/byte[]存储敏感信息

  1. 字符串变量是不可变的。一旦分配了字符串变量,就无法更改或删除其值。因此,这些字符串可能在可能在多个位置的存储器中保持不变,持续一段时间,直到垃圾收集器正好将其移除,且由于字符串是不可变的,所以没有任何方式可以修改字符串的值,因为每次修改都将产生新的字符串。敏感数据(如密码)将作为明文在内存中暴露,无法控制其生命周期因为任何能够访问内存(memory dump内存转储)的人都能清晰的看到文本中的密码,这也是为什么你应该总是使用加密的形式而不是明文来保存密码。因为String使用常量池存储字符串,即使jdk7之后常量池移到了堆,也要在触发gc之后才能彻底清除掉内存中的敏感信息。
  2. Java官方文档《Java加密体系结构指南》 (https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx) 建议:在对象java.lang.String 中收集和存储密码看似符合逻辑,但是需要注意的是,字符串对象是不可变的,没有任何方法可以改变(重写)或清空内容。这一特性使得字符串对象不适合存储安全敏感信息,比如用户密码。你应该使用字符数组收集和存储安全敏感信息。
  3. 建议使用专用类存储明文的敏感信息,或者,将明文敏感信息临时存储在可变数据类型(如:char[]/byte[])中,且用完后立即擦除。如果没有及时清空而由GC来清除的话,暴露窗口大约是秒这个数量级,如果能够在计算HASH后立即清除,暴露窗口大约是微秒数量级。如此简单的设计就可以降低如此多的被攻击概率,性价比是非常高的。
  4. 其他问题:通过reflection机制可以查看String的内部的内存成员,从而可以直接修改其中的数据区。但是这样的做法会有问题,内部化的String为了提高HASH速度,节省空间,值相同的字符串通常只有一个实例。
    你自己的char[],修改它是没有副作用的。但是String里的char[],很可能是多个String所共享的,你改掉它就会殃及别的String。举个例子,有一个密码是"Password",而你密码框提示密码输入的文字也是"Password",改掉第一个"Password"会把后面那个也改掉。

- 阅读剩余部分 -