八、类加载器2——实战
来源:互联网 发布:秒杀抢购软件 编辑:程序博客网 时间:2024/05/14 04:39
如果我们用java平台,也许在安全上我们进了一小步,这一小步对于程序员和平台管理员有一些要求,产生一些额外的工作量,这些日常的工作正如下所介绍
一、让你的程序,或者j2ee运行安全管理器
启动程序VM变量:
-Djava.security.manager -Djava.security.policy=D:/java.policy
我们可以指定多个安全文件.policy文件。只需要修改.security文件配置即可。
二、程序员可以定义自己的类加载器
package ClassLoader;import java.io.FilePermission;import java.net.URL;import java.net.URLClassLoader;import java.security.CodeSource;import java.security.PermissionCollection;import java.security.Permissions;import java.util.HashMap;public class myClassLoader extends URLClassLoader {public myClassLoader(URL[] urls) {super(urls);}public final synchronized Class loadClass(String name, boolean resolve)throws ClassNotFoundException {// 要有包的访问权限SecurityManager sm = System.getSecurityManager();if (sm != null) {int i = name.lastIndexOf('.');if (i != -1) {sm.checkPackageAccess(name.substring(0, i));}}return super.loadClass(name, resolve);}protected Class findClass(final String name) throws ClassNotFoundException {// 定义包下class的权限SecurityManager sm = System.getSecurityManager();if (sm != null) {int i = name.lastIndexOf('.');if (i != -1) {sm.checkPackageDefinition(name.substring(0, i));}}return super.findClass(name);}protected PermissionCollection getPermissions(CodeSource codesource) {// Use all the standard permissions, plus allow the code to// exit the VM.//默认由父加载器设置类的权限,URLClassLoader将会沿用java策略//PermissionCollection pc = super.getPermissions(codesource);//pc.add(new RuntimePermission("exitVM"));//pc.add(pc);//完全由自己的类加载器指定类权限FilePermission fp = new FilePermission("E:/-", "read,execute");FilePermission fp1 = new FilePermission("D:/-", "read,execute");Permissions ps = new Permissions();ps.add(fp);ps.add(fp1);return ps;}}
以上是我们自定义的类加载器,由他加载的类没有其他的权限,但是有访问D盘 、E盘文件的权限。
我们用他加载一个类,这个类主要用于访问文件,但是我们只希望加载进来的类访问E、D盘的文件,这个类加载器很好的满足了安全要求
一步一步看看!!
先定义一个接口,这个接口主要是用于访问文件,他有一个远程(第三方)的实现类
注意:请注意类加载的层次关系,层次关系不仅安全,对接口的使用也是很有用处的,父类加载器载入接口,子类就能载入接口的实现了,所以接口在应用部署上应该优先考虑,标准的接口应该尽量使用java核心包中接口。
package ClassLoader;public interface AccessFileInterface {public void readFile(String fileName);}
这个接口我们和myClassLoader放在同一个包中,由应用的加载器加载。
接着,我们在远程创建一个文件访问类,实现上面的接口
我们把接口copy到另外一个项目,并实现如下类
package classloadtest;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import ClassLoader.AccessFileInterface;public class AccessFile implements AccessFileInterface{public void readFile(String fileName){File file = new File(fileName); InputStream in = null; try { System.out.println("以字节为单位读取文件内容,一次读一个字节:"); // 一次读一个字节 in = new FileInputStream(file); int tempbyte; while ((tempbyte = in.read()) != -1) { System.out.write(tempbyte); } in.close(); } catch (IOException e) { e.printStackTrace(); return; } try { System.out.println("以字节为单位读取文件内容,一次读多个字节:"); // 一次读多个字节 byte[] tempbytes = new byte[100]; int byteread = 0; in = new FileInputStream(fileName); this.showAvailableBytes(in); // 读入多个字节到字节数组中,byteread为一次读入的字节数 while ((byteread = in.read(tempbytes)) != -1) { System.out.write(tempbytes, 0, byteread); } } catch (Exception e1) { e1.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e1) { } } }} /** * 显示输入流中还剩的字节数 */ private void showAvailableBytes(InputStream in) { try { System.out.println("当前字节输入流中的字节数为:" + in.available()); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { AccessFile a = new AccessFile(); a.readFile("D:\\testread.txt");}}
这个类实现了接口,并不能访问任何的文件,(因为java默认的配置策略赋予了他最大的权限——默认是没文件权限的),此时运行程序会抛出不能访问文件的异常,
如下的异常:
以字节为单位读取文件内容,一次读一个字节:Exception in thread "main" java.security.AccessControlException: access denied ("java.io.FilePermission" "D:\testread.txt" "read")at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)at java.security.AccessController.checkPermission(AccessController.java:559)at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)at java.lang.SecurityManager.checkRead(SecurityManager.java:888)at java.io.FileInputStream.<init>(FileInputStream.java:135)at classloadtest.AccessFile.readFile(AccessFile.java:17)at classloadtest.AccessFile.main(AccessFile.java:66)
为了让这个类有权访问文件,我们可以让myclassloader加载它
接下来,我们做一个应用,用myclassloader加载这个文件访问类
package ClassLoader;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;import java.util.Date;public class test1 {public static void main(String[] args) {URL[] urls = new URL[1];try {urls[0] = new URL("file:/E:/workspace_20140601/classloadtest/bin/");} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {//long t_s = (new Date()).getTime();URLClassLoader ucl = new myClassLoader(urls);//ucl.loadClass("classloadtest.AccessFile");//ucl.loadClass("classloadtest.AccessFile1");//long t_s2 = (new Date()).getTime();//System.out.println(t_s-t_s2);Class<?> c = ucl.loadClass("classloadtest.AccessFile");AccessFileInterface acc = (AccessFileInterface)(c.newInstance());acc.readFile("d:/testread.txt");//long t_s3 = (new Date()).getTime();//System.out.println(t_s-t_s3);Class<?> c1 = ucl.loadClass("classloadtest.AccessFile1");AccessFileInterface acc1= (AccessFileInterface)(c1.newInstance());acc1.readFile("e:/testread1.txt");//long t_s4 = (new Date()).getTime();//System.out.println(t_s-t_s4);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
这个应用使用myClassLoader加载Accessfile类, 并给这个类相应的权限-----d、e盘所有的访问权限,
现在这个类能够访问所有的d、e盘下的文件了,没有异常发生了,另外由这个加载器加载的其他类都有这个权限了。
可以说,这个类加载器的所有URL资源被加载后,都会得到相应的文件访问权限,除非这个资源路径被父加载器覆盖。
另外,要注意,类加载赋予类权限的代码是特权代码。也许这就是漏洞哦,没有绝对的安全,就像你信任你的朋友,但是朋友也可能会坑害你一样,人为因素才是安全的伦理。
所以,我们最好是只读取签名的jar,提供完善的代码源,这样就能设定——谁签名的jar有多大的权限,这样我们能在平台上更方便引用第三放的类库,并设置安全了,虽然不能做到绝对安全,但是如果大家都有共同的利益所在,估计是不会让原子弹提前爆发的。
- 八、类加载器2——实战
- 八、类加载器
- vtk实战(八)—读取.raw文件
- 深入理解JVM(八)——类加载的时机
- 深入理解JVM(八)——类加载的时机
- 深入理解JVM(八)——类加载的时机
- 深入理解JVM(八)——类加载的时机
- JVM(八) 类加载器
- Java自定义类加载器实战
- Java虚拟机(八):自定义类加载器
- (八)Tomcat源码解析 - Tomcat类加载器原理
- scala 学习(八)——lazy加载和try
- Hibernate学习笔记(八) — 懒加载与抓取策略
- JVM学习笔记(八)类加载机制-类加载器
- 微信小程序之上拉加载(分页加载)实例 —— 微信小程序实战系列(2)
- jvm探秘八:类加载机制之类加载过程
- VC++实战OLEDB编程(八)——行状态与延迟更新
- VC++实战OLEDB编程(八)——行状态与延迟更新(转)
- W3C
- ios 上一些好的自定义控件收集
- mongoDB 入门指南、示例
- 办公用什么pdf分割软件
- 【机房重构】字符类型之间的比较
- 八、类加载器2——实战
- DownloadManager的使用方法:一
- 简单的学生信息管理系统
- 使用Scenes和Transitions执行动画 -- Animating Views Using Scenes and Transitions
- 态度决定一切---高效程序员的45个习惯读书笔记
- C++ struct
- Android开发知识整理
- C语言全局变量多文件使用
- Apache目录访问权限配置详解