[Java Security]Java资源访问的安全控制

2017-01-13 15:00:07来源:csdn作者:qq_24759299人点击

第七城市
Java资源访问的安全控制

在JDK的API中经常会看到SecurityManager的应用,例如System.getProperty:

public static String getProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key);
}

不了解Java安全体系的话,可能并不知道中间几行代码的具体作用。本文先简单介绍下Java安全体系中的资源访问控制机制。

1. 资源访问控制

要控制Java程序的资源访问权限,主要有两点: 一是,定义访问策略,即java policy文件,简单的说就是资源访问授权,默认的policy文件为$JAVA_HOME/jre/lib/security/java.policy,内容如下:

// Standard extensions get all permissions by defaultgrant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
};// default permissions granted to all domainsgrant {
// Allows any thread to stop itself using the java.lang.Thread.stop()
// method that takes no argument.
// Note that this permission is granted by default only to remain
// backwards compatible.
// It is strongly recommended that you either remove this permission
// from this policy file or further restrict it to code sources
// that you specify, because Thread.stop() is potentially unsafe.
// See the API specification of java.lang.Thread.stop() for more
// information.
permission java.lang.RuntimePermission "stopThread";// allows anyone to listen on un-privileged ports
permission java.net.SocketPermission "localhost:1024-", "listen";// "standard" properies that can be read by anyonepermission java.util.PropertyPermission "java.version", "read";
permission java.util.PropertyPermission "java.vendor", "read";
permission java.util.PropertyPermission "java.vendor.url", "read";
permission java.util.PropertyPermission "java.class.version", "read";
permission java.util.PropertyPermission "os.name", "read";
permission java.util.PropertyPermission "os.version", "read";
permission java.util.PropertyPermission "os.arch", "read";
permission java.util.PropertyPermission "file.separator", "read";
permission java.util.PropertyPermission "path.separator", "read";
permission java.util.PropertyPermission "line.separator", "read";permission java.util.PropertyPermission "java.specification.version", "read";
permission java.util.PropertyPermission "java.specification.vendor", "read";
permission java.util.PropertyPermission "java.specification.name", "read";permission java.util.PropertyPermission "java.vm.specification.version", "read";
permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
permission java.util.PropertyPermission "java.vm.specification.name", "read";
permission java.util.PropertyPermission "java.vm.version", "read";
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};

授予JDK的ext目录下代码全部访问权限,授予其余任意代码的一系列默认权限。 使用Java自带的policytool工具可以创建Policy文件,具体参考Policy File Creation and Management

二是,启动SecurityManager,默认情况下Java是不启动安全检查的。运行Java程序需带上-Djava.security.manager参数即可启动安全校验,例如:

java -Djava.security.manager SecurityTest

只此两步即可开启资源访问的授权控制。

2. 访问控制示例

编写一段代码,完成读取系统属性、读文件、写文件三个操作,示例如下:

public static void main(String[] args) throws Exception {
// properties
System.out.println("properties:");
String[] properties = { "os.name", "java.version", "java.home", "user.home", "java.ext.dirs" };
for (String prop : properties) {
String value = System.getProperty(prop);
System.out.println(prop + " = " + value);
}// read file
System.out.println();
System.out.println("read file:");
String file = "E://download//col_iplib.txt";
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String line = reader.readLine();
System.out.println("read line: " + line);
reader.close();// write file
System.out.println();
System.out.println("write file:");
file = "E://download//security-test.txt";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
line = "test java security";
writer.write(line);
writer.newLine();
System.out.println("write line: " + line);
writer.close();
}

在不开启安全检查时,可以正常运行,结果如下:

E:/workspace/proj/alg/target/classes>java com.github.myron.security.SecurityTest
properties:
os.name = Windows 7
java.version = 1.8.0_40
java.home = C:/Program Files/Java/jre1.8.0_40
user.home = C:/Users/gengmaozhang01
java.ext.dirs = C:/Program Files/Java/jre1.8.0_40/lib/ext;C:/windows/Sun/Java/lib/extread file:
read line: 1.0.1.0|1.0.3.255:CN|福建|None|None|CHINANET|None|Nonewrite file:
write line: test java security

当开启安全检查时,即会报错。

E:/workspace/proj/alg/target/classes>java -Djava.security.manager com.github.myron.security.SecurityTest
properties:
os.name = Windows 7
java.version = 1.8.0_40
Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.home" "read")
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPropertyAccess(Unknown Source)
at java.lang.System.getProperty(Unknown Source)
at com.github.myron.security.SecurityTest.main(SecurityTest.java:30)

因为Java默认的java.policy文件并未授予所有程序读取java.home的权限,及文件读写权限。

使用policytool工具创建自己的policy文件,授予上述系统属性、文件读写的权限,如下: 生成的policy文件如下:

/* AUTOMATICALLY GENERATED ON Sun Oct 23 20:30:42 CST 2016*/
/* DO NOT EDIT */grant codeBase "file:/E:/workspace/proj/alg/target/classes/*" {
permission java.io.FilePermission "<<ALL FILES>>", "read, write";
permission java.util.PropertyPermission "java.home", "read";
permission java.util.PropertyPermission "user.home", "write, read";
permission java.util.PropertyPermission "java.ext.dirs", "read";
};

使用-Djava.security.policy参数指定该policy策略,执行正常:

E:/workspace/proj/alg/target/classes>java -Djava.security.manager -Djava.security.policy=E:/download/my.java.policy com.github.myron.security.SecurityTest
properties:
os.name = Windows 7
java.version = 1.8.0_40
java.home = C:/Program Files/Java/jre1.8.0_40
user.home = C:/Users/gengmaozhang01
java.ext.dirs = C:/Program Files/Java/jre1.8.0_40/lib/ext;C:/windows/Sun/Java/lib/extread file:
read line: 1.0.1.0|1.0.3.255:CN|福建|None|None|CHINANET|None|Nonewrite file:
write line: test java security3. 自定义权限控制

在具体项目中,除了常见的系统资源,还有其他业务资源需要进行访问控制,这里就以消息服务为例来演示自定义的权限控制。

首先,定义自己的资源权限,如下:

public class MessagePermission extends BasicPermission {private static final long serialVersionUID = -6179037573716029507L;public static final String MESSAGE_READ_ACTION = "readMessage";
public static final String MESSAGE_WRITE_ACTION = "writeMessage";private String actions;public MessagePermission(String name) {
super(name);
}public MessagePermission(String name, String actions) {
// NOTE: actions is ignored by BasicPermission
super(name, actions);
this.actions = actions;
}@Override
public String getActions() {
return actions;
}// 简单的Actions比较实现,更精细的实现可参考PropertyPermission
@Override
public boolean implies(Permission p) {
if (super.implies(p)) {
MessagePermission mp = (MessagePermission) p;
if (mp.getActions() == null || mp.getActions().isEmpty()) {
return true;
}
if (this.actions == null || this.actions.isEmpty()) {
return false;
}
if (this.actions.contains(mp.getActions())) {
return true;
}
return false;
}
return false;
}}

然后,编写有安全校验的消息读写程序,代码如下:

public class SecurityMessageService {public static final String MESSAGE_NAME = "SecurityMessage";public void readMessage() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new MessagePermission(MESSAGE_NAME, MessagePermission.MESSAGE_READ_ACTION));
}
// do something
System.out.println("read message done");
}public void writeMessage() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new MessagePermission(MESSAGE_NAME, MessagePermission.MESSAGE_WRITE_ACTION));
}
// do something
System.out.println("write message done");
}public static void main(String[] args) {
SecurityMessageService messageService = new SecurityMessageService();// read
messageService.readMessage();
// write
messageService.writeMessage();
}}

直接开启安全检查执行,抛出了无消息读写权限的异常:

E:/workspace/proj/alg/target/classes>java -Djava.security.manager com.github.myron.security.SecurityMessageService
Exception in thread "main" java.security.AccessControlException: access denied ("com.github.myron.security.MessagePermis
sion" "SecurityMessage" "readMessage")
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at com.github.myron.security.SecurityMessageService.readMessage(SecurityMessageService.java:17)
at com.github.myron.security.SecurityMessageService.main(SecurityMessageService.java:36)

最后,创建policy策略文件,授予消息读写权限,如下:

/* AUTOMATICALLY GENERATED ON Sun Oct 23 22:17:00 CST 2016*/
/* DO NOT EDIT */grant codeBase "file:/E:/workspace/proj/alg/target/classes/*" {
permission com.github.myron.security.MessagePermission "SecurityMessage", "readMessage,writeMessage";
};

执行正常完成,结果如下:

E:/workspace/proj/alg/target/classes>java -Djava.security.manager -Djava.security.policy=E:/download/message.policy com.github.myron.security.SecurityMessageService
read message done
write message done

参考: 1. Trail: Security Features in Java SE 2. 自定义java.policy配置 3. Java程序访问权限控制(policy文件)


第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台