当竞争对手的应用程序与我们的应用程序执行在同一个系统上时,我们的应用程序在内存中的敏感数据是非常easy被竞争对手获取的。假设我们的应用程序符合以下几种情况之中的一个,那么竞争对手能够获取到我们应用的敏感数据:

1)应用程序使用对象来存储敏感数据,并且在对象使用完后。对象的内容没有被清除或者对象没有被垃圾回收;

2)在操作系统执行内存管理任务或者执行休眠等功能时。应用程序的内存分页将被置换到磁盘上保存;

3)持有存储了操作系统缓存或者内存中敏感数据的buffer对象(比如BufferedReader)。

4)基于反射的控制流。使得竞争对手能够使用规避措施逃过敏感变量生命周期的限制;

5)在调试信息/日志文件/环境变量或者线程和core dumps等方面泄漏了敏感数据。

包括敏感数据的内存在数据使用后没有及时清空,非常easy导致敏感数据的泄漏。

为了限制这样的风险。应用程序必须尽量减小敏感数据的生命周期。

完美的防止内存数据的泄漏要求底层操作系统和Java虚拟机的支持。比如假设将内存数据置换到磁盘上是存在安全问题的,那么一个安全的操作系统就须要禁用数据的置换和系统的休眠。

[不符合安全要求的代码演示样例]

以下代码从控制台读取用户的username和password并将password保存在一个String对象中,这导致在垃圾回收器回收String所占用的内存之前,password处于泄漏状态。

import java.io.Console;
import java.io.IOException; public class Password { public static void main(String[] args) throws IOException {
Console console = System.console();
if (console == null) {
System.out.println("No Console.");
System.exit(1);
} String username = console.readLine("Enter your user name:");
String password = console.readLine("Enter your password:");
if (!verify(username, password)) {
throw new SecurityException("Invalid Credentials");
} } // dummy verify method, always returns true
private static final boolean verify(String username, String password) {
return true;
} }

[符合安全要求的解决方式]

这个解决方式使用Console.readPassword()函数从控制台中获取password

import java.io.Console;
import java.io.IOException;
import java.util.Arrays; public class Password { public static void main(String[] args) throws IOException {
Console console = System.console();
if (console == null) {
System.out.println("No Console.");
System.exit(1);
} String username = console.readLine("Enter your user name:");
char[] password = console.readPassword("Enter your password:");
if (!verify(username, password)) {
throw new SecurityException("Invalid Credentials");
} // Clear the password
Arrays.fill(password, ' '); } // dummy verify method, always returns true
private static final boolean verify(String username, char[] password) {
return true;
} }

函数Console.readPassword()使得返回的数据是字节数组类型,而不是String对象。因此。开发人员能够在数组数据使用完了之后清空数据,这个函数同一时候禁止了password在控制台上面的显示。

[不符合安全要求的代码演示样例]

以下的代码使用BufferedReader对象包装InputStreamReader对象,这导致敏感数据能够直接在文件里读取到。

	void readData() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("file"))); // read from file
String data = br.readLine();
}

BufferdReader.readLine()函数将敏感数据以String对象的形式返回,这个对象在敏感数据用完之后还会存活非常长的时间。

而BufferedReader.read(char[], int, int)函数能够将敏感数据读取到一个char数组中。只是这须要开发人员在使用完敏感数据后手动清除。类似的,假设使用BufferedReader来包装FileReader对象。也会存在相同的安全问题。

[符合安全要求的解决方式]

以下的代码使用直接分配的NIO buffer来从文件里读取敏感数据。在数据使用完后。能够马上清除它,并且敏感数据不会缓存在多个位置,仅存在于系统内存中。

	void readData() {
ByteBuffer bb = ByteBuffer.allocateDirect(16*1024);
try (FileChannel rdr = (new FileInputStream("file")).getChannel()) {
while(rdr.read(bb) > 0) {
// do something with the buffer
bb.clear();
}
} catch(Throwable e) {
// Handle error
}
}

须要注意的是,必须手动清除buffer里面的数据,由于这部分数据垃圾回收器是不会进行回收的。

——欢迎转载,请注明出处 http://blog.csdn.net/asce1885 。未经本人允许请勿用于商业用途。谢谢——

【Java编码准则】の #01限制内存中敏感数据的生命周期的更多相关文章

  1. 【Java编码准则】の #02不要在client存储未加密的敏感信息

    当构建CS模式的应用程序时,在client側存储敏感信息(比如用户私要信息)可能导致非授权的信息泄漏. 对于Web应用程序来说,最常见的泄漏问题是在client使用cookies存放server端获取 ...

  2. 【Java编码准则】の #13使用散列函数保存password

    明文保存password的程序在非常多方面easy造成password的泄漏.尽管用户输入的password一般时明文形式.可是应用程序必须保证password不是以明文形式存储的. 限制passwo ...

  3. 【Java面试题】解释内存中的栈(stack)、堆(heap)和静态存储区的用法

    Java面试题:解释内存中的栈(stack).堆(heap)和静态存储区的用法 堆区: 专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型 ...

  4. JAVA面试题:Spring中bean的生命周期

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  5. (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期

    日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...

  6. 简:Spring中Bean的生命周期及代码示例

    (重要:spring bean的生命周期. spring的bean周期,装配.看过spring 源码吗?(把容器启动过程说了一遍,xml解析,bean装载,bean缓存等)) 完整的生命周期概述(牢记 ...

  7. IoC基础篇(一)--- Spring容器中Bean的生命周期

    日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...

  8. 面试突击80:说一下 Spring 中 Bean 的生命周期?

    Java 中的公共类称之为 Bean 或 Java Bean,而 Spring 中的 Bean 指的是将对象的生命周期,交个 Spring IoC 容器来管理的对象.所以 Spring 中的 Bean ...

  9. 深入理解Spring中bean的生命周期

    [Spring中bean的生命周期] bean的生命周期 1.以ApplocationContext上下文单例模式装配bean为例,深入探讨bean的生命周期: (1).生命周期图: (2).具体事例 ...

随机推荐

  1. mac打包python3程序

    1. 下载安装py2app pip3 install py2app 2. 创建setup.py文件 py2applet --make-setup XXX.py 3. 发布应用 python3 setu ...

  2. 紫书 例题 10-16 UVa 12230(数学期望)

    感觉数学期望的和化学里面求元素的相对原子质量的算法是一样的 就是同位素的含量乘上质量然后求和得出 这道题因为等待时机是0到2*l/v均匀分配的,所以平均时间就是l/v 再加上过河的l/v, 最后加上步 ...

  3. oracle基础入门(四)

    一:其实oracle的语法跟sql servce 挺像的只有一些个别的差异而已 1):安装Oracle的数据库一般它的表中会自带了两站表: 是 emp(员工表) , dept(部门) 单表查询 sel ...

  4. 洛谷 P2630 图像变换

    P2630 图像变换 题目描述 给定3行3列的图像各像素点灰度值,给定最终图像,求最短.字典序最小的操作序列. 其中,可能的操作及对应字符有如下四种: A:顺时针旋转90度: B:逆时针旋转90度: ...

  5. mysql生成随机时间

    mysql> update test set create_time=concat('2013-10-01 ', floor(10+rand()*10),':',floor(10+rand()* ...

  6. BOOST_CLASS_EXPORT

    用基类的指针去转存派生类时除了上一篇boost::serialization 用基类指针转存派生类(错误多多,一波三折)之外.还有还有一种更简单的方法: 用BOOST_CLASS_EXPORT宏. 以 ...

  7. OC07 -- 迭代器/NSNumber/NSValue/NSRange/NSSet/NSDate 及相互转换.(杂)

    //一: 迭代器 //数组 NSArray *arr=@[@"1",@"2",@"3",@"4",@"5&qu ...

  8. vue20 父子组件数据交互

    子组件使用父组件数据 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  9. .net数字转换成汉字大写

    public class Num2Rmb { private String[] hanArr={"零","壹","贰","叁&qu ...

  10. BZOJ 1103 DFS序+线段树

    思路: 先搞出来DFS序 进入这个点 +1 出这个点 -1 线段树维护前缀和 (因为还要修改) 搞定 修改的时候只修改底下节点就OK了 (边权–>点权 不多说) //By SiriusRen # ...