java源代码(共6篇)
java源代码 篇1
摘要:研究了常见的SQL注入检测和源代码静态分析扫描的原理,提出Java源代码SQL注入检测算法,该算法通过对Java源代码词法分析和语法分析、建立抽象语法树、定义规则、遍历语法树和跟踪等,检测Java源代码中可能的SQL注入路径,测试结果表明,算法检测效果良好,识别率高。
关键词:静态分析,SQL注入,抽象语法树
SQL注入攻击是一种常见的互联网攻击手段,它具有易操作、强隐蔽、高危害和难检测等特点。由于SQL注入攻击的对象是Web服务器后台的数据库,而数据库往往存放重要的用户数据或业务数据,因而SQL注入攻击的后果影响非常严重。特别对银行、证券、电信、移动、政府以及电子商务企业等后台数据库。一旦遭受SQL注入而导致数据纂改或机密数据丢失,在经济角度和社会角度都将产生恶劣的影响。因此检测和防范SQL注入是软件安全领域的重要课题,具有极高的研究价值和意义。
常见的Web应用系统架构如图1所示,其中包括Web服务器及后台数据库。在Web服务器上部署Web服务,用户使用浏览器通过Http或Https协议与Web服务器进行交互。常称之为B/S架构。
在该架构中,Web服务器向用户提供各种应用服务这些服务都涉及到与数据库的交互,即伴执行SQL语句。如果Web应用系统设计或实现不合理,将可能导致用户对数据库执行的SQL语句偏离系统设计的预期,从而引发安全事故。
Java程序运行在JVM中,因为具有与平台无关的特点,这种完全面向对象开发的语言广泛应用在Web系统的设计中。针对Java源代码的SQL注入攻击检测进行研究,对于提高Web应用系统的安全性具有重要意义。
本文介绍了SQL注入原理、目前的检测方法以及Java代码对数据库操作的三种代码结构。针对Java执行SQL语句的特点,重点提出一种基于抽象语法树进行SQL执行路径检测的SQL注入检测算法;在Web应用程序发布前进行深入静态分析和检查,从而提高Web应用系统的安全性。算例分析和在实际Web系统中的应用结果表明,本文提出的SQL注入检测算法具有高检测率和低误报率。
1 相关研究工作
SQL注入漏洞最早在2000年左右被提出,其后学者们对SQL注入的检测和防护展开了一系列的研究。
典型的一种SQL注入例子如下:
(1)用户登录Web应用系统时,需要进行身份认证,主要输入用户名和密码两个变量v_usr和v_pwd;
(2)Web系统执行合法性检查的SQL语句为:“Select*from users where username=‘”+v_usr+“’and password=‘”+v_pwd+“’”,如果用户登录时用户取为‘admin’or1=1--,那么合法性检查的SQL语句等效于Select*from users where username=‘admin’or 1=1;
显然,用户名取‘admin’or 1=1--时,无论密码输入多少,都可以登录系统。
SQL注入的检测和防护方式目前主要有两大类,一是系统上线前检测,也称为静态检测;二是系统在线运行防御,也称为动态检测。
动态检测方式是一种黑盒检测方法,对上线的系统进行SQL漏洞扫描,编制SQL注入攻击脚本对Web系统进行试探,通过检查Http的回应报文内容来判断是否发生SQL注入攻击,从而确定是否存在SQL注入漏洞。AppScan等工具可执行此类安全检测。
静态检测方法是一种白盒检测方法[1],通过静态语法解析查找Web应用代码中可能引发SQL注入的环节,在Web应用发布前检查代码质量。Fotify等工具可执行此类安全检测。参考文献[2,3]给出一种动态生成SQL语句进行类型正确性检查的方法来检测是否存在SQL注入,该方法的的缺点在于只能检测句法结构或语句类型出现异常的SQL注入问题。参考文献[4]提出一种自动推理机的方法对添加了输入值后的SQL语句进行检查,该方法的缺点在于只能检测出重言式的SQL注入攻击。此外,还有一些学者采用机器学习算法对SQL注入漏洞进行检测[5],这一类检测方法的检测率和误报率往往依赖于训练集的大小。
2 Java源代码静态扫描分析思路
程序静态分析指在不执行程序的情况下,通过自动扫描代码发现隐含的程序隐患[6],具备执行速度快、效率高等优点。对源代码进行静态分析时借鉴编译技术的词法分析和语法分析。源代码进行静态分析扫描原理如图2所示。
Java程序与数据库之间的交互主要通过Java数据库连接JDBC进行。其数据库操作涉及与数据库建立连接、发送SQL指令、处理返回结果、断开数据库连接4个步骤。
具体实现上主要涉及的Java类有Connection类、DriverManager类、Statement类、ResultSet类、PreparedStatement类和callableStatement类。在代码实现上往往有3种实现方式:
(1)常规方式
Java采用常规方式访问数据库,每次都需要进行建立连接,再执行SQL语句,最后释放连接。由于建立连接过程一般比较耗时(一般需要几十毫秒至几百毫秒之间),而且Statement对象每次执行SQL语句的解析和编译也比较耗时,如果涉及如下循环使用情况,则代码的执行效率将会比较低下。为此,对于需要频繁建立数据库连接的情况,可以采用连接池方式进行优化;对于需要频繁执行相似SQL语句的情况,则可采用预编译方式进行优化。
(2)预编译方式
采用常规方式执行SQL语句时,DBMS需要对SQL语句进行解析和编译;而采用预编译方式时,DBMS只在第一次对SQL语句进行解析和编译。相比前者,后者更难注入SQL。原因在于,PreparedStatement对象执行SQL语句前,需要设置“?”号对应的变量,例如ps.setInt(1,变量v1)、ps.setLong(2,变量v2)表示SQL语句中第一个“?”号是int型、值为“变量v1”;这样在安全性上相当于增加了一个类型匹配。
(3)连接池方式
连接池(Connection Pool)是设计模式中资源池(Resource Pool)的一种具体应用,主要解决资源频繁分配和释放所带来的性能问题。其基本思想是预先建立一个数据库连接池,在该连接池中预先存放一定数量的连接,当需要建立数据库连接时,并非新建一个数据库连接,而是从连接池中取出一个连接对象,然后对该连接对象进行参数设置和使用,使用完毕后,并不释放该连接,而是将连接对象的参数复位并回收。
采用连接池的应用开发方式与常规方式的代码结构类似。区别是常规方式的连接对象在需要时才从堆中动态分配空间与数据库建立连接,使用完毕后即断开连接,等待Java的GC垃圾回收器发现该对象不再需要后,将回收连接对象的内存空间;而采用连接池方式,则是在连接池中预先建立一个若干数据的连接对象,需要使用时才从连接池中取出一个连接对象(不是临时创建,因此效率高),使用完毕后,并不断开连接,而是将该连接对象归还给对象池。通过一个“借用”和“归还”的方式使得可以高效地对付频繁的数据库访问操作。目前常用的连接池主要有C3PO、BoneCP、DBCP、Proxool等。
综上所述,无论采用哪一种数据库操作方式,Java源代码中可能出现SQL注入漏洞的代码执行过程中,一定经过executeQuery、executeUpdate、execute或executeBatch函数。本文提出的SQL检测算法,正是通过定位这些函数并以此为分析SQL注入隐患的切入点,跟踪这些函数的参数或参数表达式。如果这些参数表达式最终能追溯到某个特定的对象(如HttpServletRequest),则可以肯定这条路径将可能存在SQL注入隐患。
3 Java源代码SQL注入检测算法
抽象语法树AST(Abstract Syntax Tree)是程序源代码的抽象语法结构的树状表现形式,树上的每个节点表示源代码中的一种结构,AST的好处在于不依赖于具体的方法和语言细节。对于源代码的文法分析,首先进行词法分析,将源代码中所有字符串从前至后逐个字符进行扫描,并对每个“单词”进行标识。这些“单词”主要包括Java语言中的关键字、标识符、运算符和分隔符等。然后进行语法分析,将这些识别出来的“单词”序列分解成各类Java语法单位。
根据源代码静态分析扫描原理,结合Java 1.6的文法定义,本文提出的SQL注入检测算法通过对源代码的词法和语法分析,生成相应的抽象语法树,定义规则,根据规则遍历抽象语法树。
本文提出的检测算法实现步骤如下:
(1)遍历抽象语法树,寻找METHOD_DECL结点中节点名为executeQuery或executeUpdate或execute或executeBatch的所有节点,并将它们保存在哈希表keyNode中。
(2)找keyNode中的每一个节点,确认是否是正确的结点。首先得到keyNode节点的前继表达式,并得到前继表达式的返回值类型。若前继表达式的返回值类型为Java.sql.Statement,则可确认此结点,并转到下一步;若返回值类型不是Java.sql.Statement,则转步骤(2),检测下一个节点;
(3)确认结点,取得第一个参数作为路径结点,分析并跟踪路径结点的数据流。具体为:分析并跟踪路径结点表达式为变量表达式;分析并跟踪路径结点表达式为方法表达式;跟踪退出的准则描述如下:(1)当所有跟踪变量均到达常量定值,则此路径不会产生SQL注入漏洞,转步骤(2);(2)跟踪到开始API定义的方法结点,转步骤(4)。
(4)记录跟踪到的SQL注入的侵入路径,转步骤(2),检测下一个节点。若keyNode中所有结点都已检测完成,则算法终止。
4 算法实验
为了验证本文提出的算法的有效性,以一个Java程序为实验算例进行分析和说明,实验算例代码如图3所示。
在实验的Java源代码中,可能产生SQL注入的开始API和结束API(即Java源代码SQL注入检测规则),具体如表1所示。
根据SQL注入检测规则,利用本文所提出的检测算法对图3所示的Java源代码进行扫描分析,产生的抽象语法树如图4所示,可发现SQL注入漏洞,并报告相应的路径。
本文提出的SQL注入检测算法已经成功应用于本单位信息系统的Java源代码静态检测中。在新上线运行的某Web系统(约10万行代码)静态分析中,检测时间仅为5 s,检测准确识别率高达90%,而误报率仅有10%;通过实验和实际系统的测试和验证,本文提出的Java源代码SQL注入静态分析算法具有很好的应用效果和前景。
参考文献
[1]WILLIAM G J,VIEGAS H J,ORSO A.A classification ofSQL injection attacks and countermeasures[C].Proc.of In-ternational Symposium on Secure Software Engineering.2006.
[2]GOULD C,SU Z,DEVANBU P.JDBC checker:a staticanalysis tool for SQL/JDBC applications[C].Proceeding ofthe 26th International conference on Software Engineering(ICSE).Washington D C:IEEE computer Society,2004.
[3]GOULD C,SU Z,DEVANBU P.Static checking of dyn-amically generated queries in database applications[C].Pro-ceedings of 26th International Conference on Software Engi-neering,2004.
[4]WASSERMANN G,SU Z.An analysis framework for secu-rity in Web applications[C].Proceedings of the FSE Work-shop on Specification and Verification of Component-Based System,2004.
[5]HUANG Y W,HUANG S K,LIN T P,et al.Web appli-cation security assessment by fault injection and behaviormonitoring[C].Porceeding of the 11th International WorldWide Conferecne,2002.
[6]张卓.SQL注入攻击技术及防范措施研究[D].上海:上海交通大学,2007.
java源代码 篇2
import java.awt.*;import java.net.*;import java.awt.event.*;import java.io.*;import java.applet.*;class AudioClipWindow extends Frame implements Runnable,ItemListener,ActionListener { Thread thread;
Choice choice;
URL url;
AudioClip clip;
Button buttonPlay,buttonLoop,buttonStop;
String str;
AudioClipWindow(ActionListener chatClient)
{
thread=new Thread(this);
choice=new Choice();
choice.add(“陈绮贞-我在那一角落患过伤风.wav”);
choice.add(“no one wants forever.wma.wav”);
choice.add(“中岛美嘉-雪之华(韩雪-飘雪)日文版.wav”);
choice.addItemListener(this);
buttonPlay=new Button(“播放”);
buttonLoop=new Button(“循环”);
buttonStop=new Button(“停止”);
buttonPlay.addActionListener(this);
buttonStop.addActionListener(this);
buttonLoop.addActionListener(this);
setLayout(new FlowLayout());
add(choice);
add(buttonPlay);
add(buttonLoop);
add(buttonStop);
setSize(350,120);
setVisible(true);
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e)
{ System.exit(0);
}
});
validate();
}
public void itemStateChanged(ItemEvent e)
{ str=choice.getSelectedItem();
if(!(thread.isAlive()))
{ thread=new Thread(this);
}
try{ thread.start();
}
catch(Exception ee){}
}
public void run()
{ try{ File file=new File(str);
url=file.toURL();
clip=Applet.newAudioClip(url);
}
catch(Exception e)
{ System.out.println(e);
}
}
public void actionPerformed(ActionEvent e)
{ if(e.getSource()==buttonPlay)
{ clip.play();
}
else if(e.getSource()==buttonLoop)
{ clip.loop();
}
if(e.getSource()==buttonStop)
{ clip.stop();
}
基于Java代码重用性的研究 篇3
1 代码重用的优势
在进行Java应用的开发过程中,有经验的软件工程师往往将项目中那些经常出现的一些功能相同的代码进行必要的管理,因为这样做往往会使得程序变得更加简练、清晰和易于维护,其中一个重要的方法的就是进行必要的代码重用。事实上,进行代码重用不但可以提高程序开发的效率,而且还能够将一些比较实用的代码有效地运用到其它的项目中,可以节约软件开发的成本,提高软件生产的效率,同时还能够增加代码的可靠性和增强被重用代码与系统函数的其他部分具有较强的一致性。
2 代码重用的策略
在实际的应用开发过程中,究竟要怎样做才能更有效地进行代码重用呢?下面拟就这一问题提出几个在Java应用开发中进行代码重用的解决策略:
2.1 面向接口编程
在Java程序设计过程中,实现代码重用的一个非常重要策略就是面向接口编程。在接口中,它规定了实现本接口的类或接口必须拥有的一组规则,它是在一定粒度视图上同类事物的抽象表示。而面向接口编程就是使用接口和同类型的组件进行通讯。在实际的程序设计中,往往是从那些具有相同功能的组件中抽象出一个接口(interface)或者一个抽象类(abstract class)。这样,当需要用其它组件完成任务时,只需要替换该接口的实现,而程序代码的其它部分则不需要改变。若现有的组件不能满足要求时,可以创建新的组件,实现该接口,或者直接对现有的组件进行扩展,由子类去完成扩展的功能。
在具体开发实践中,通常从下面两个方面来使用接口:一是把参数类型改成接口,二是尽量选择最简单的参数接口类型。
(1)把参数类型改成接口
众所周知,在Java语言里,如果某个方法的所有参数都是对一些已知接口的引用,那么这个方法就能够操作那些实际上可能还没有实现该接口的类的对象。在实际编程中,若某块代码能够编写为独立的public方法时,只要能够把它所有类形式的参数改为接口形式,那么方法的参数就可以是实现了该接口的所有类的对象,而不仅仅是原来的类所创建的对象。这样,该方法就能够对可能存在的大量的对象类型进行操作。
例如,对于下面的public静态方法:
static public boolean contains(Rectangle rect,int x,int y){……}
若将rect参数的类型Rectangle类改变成接口类型:
public interface Rectangular{Rectangle get Bounds();}
那么所有可以描述为矩形的类(即,实现了Rectangular接口的类)所创建的对象都可以作为提供给contains(Rectangle rect,int x,int y){……}的rect参数,这样,显然提高了代码的重用性。这种通过放宽参数类型的限制,即把方法的参数类型改成接口是实现代码可重用性的一个很好的方法。
(2)选择最简单的参数接口类型
在把参数的类型改为接口类型时,可能存在多种实施方案,在这些方案中,对代码重用最有价值的应是那种既能完全满足方法对参数的需求,同时又具有最少的多余代码和数据的方案。事实上,描述参数对象要求的接口越简单,其他类实现该接口的机会就越大,其对象能够作为参数使用的类也越多。下面以一个简单的例子来说明这一点:
static public boolean are Overlapping(Window window1,Window window2){……}
这个方法用于检查两个窗口(假定是矩形窗口)是否重叠。如果这个方法只要求从参数获得两个窗口的矩形坐标,此时相应地简化这两个参数是一种更好的选择:
static public boolean are Overlapping(Rectangular rect1,Rectangular rect2){……}
上面的代码假定Window类型实现了Rectangular接口。经过改动之后,对于任何矩形对象我们都可以重用该方法的功能。
2.2 代码分离
由于Java面向对象的特点,继承的方法无疑也能实现代码的重用,但这并不是最理想的方法。因为,继承总是带来一些多余的方法和数据成员,这样就会使得重用类里面的某个方法的代码变得复杂;另外,派生类对父类的依赖关系也会使得代码更加复杂:因为对父类的改动就极可能影响到子类;同时,修改父类或者子类中的任意一个类时,则很难记得哪一个方法被子类覆盖,哪一个方法没有被子类覆盖;最后,子类中的覆盖方法是否要调用父类中的对应方法有时并不是那么明显。这样,仅仅通过继承来实现代码的重用就存在一定的不足。在实际编程中,通常是将继承与代码分离技术相结合来实现代码的重用。
所谓代码分离就是将可变的部分和不可变的部分分离开来,它是面向对象设计的一个重要原则。在通过继承进行代码重用的时候,可以在抽象基类中定义好不可变的部分,而由其子类去具体实现可变的部分,这样,不可变的部分就不需要重复定义,而且也便于维护。
2.3 改写类的实例方法
在实际编程中,代码重用的首选应是那些执行单一概念任务的方法。为了重用这些代码,可把类的某些实例方法移出成为全局性的过程。若要提高这种过程的可重用性,过程代码应该象静态工具方法一样进行编写:即它只能使用自己的输入参数,并调用其他全局性的过程,但不能使用任何非局部的变量。显然,这种对外部依赖关系的限制简化了过程的应用,从而使得过程能够方便地用于任何地方。
众所周知,在Java中,方法是不能脱离类而单独存在的。因此,为了实现代码的重用,就可以将相关的过程进行有效的组织并使它们成为一个独立类中的公共静态方法。
例如,对于如下所示的一个类:
不难看出,p Polygon类所封装的过程主要是与该类对象相关的一些方法。在这个例子中,Polygon类的功能就由p Polygon类以过程为单位进行提供。这样,对代码改动的结果就使得客户在重用这些代码时只使用自己需要的代码,而无需关心那些并不需要的功能。
3 代码重用的不足
尽管代码重用的优势是明显的,但要注意的是,代码重用同样存在一些不足,主要表现在以下几方面:
3.1 通用性的限制
一般来说,只有通用性较强的代码才具有重用的意义,如果对于那些没有明确地为通用性而设计的代码,就企图在多个项目间进行代码重用,即使是在同一机构里使用也并不会享受到代码重用带来的好处,反而会给整个编程带来重重困难。
3.2 依赖度高
如果重用的代码不是作为一个行业的标准框架和库,那么当这样的代码积累得越多,反而越是需要依赖于现有的开发人员,同时,对于新加入的开发人员在搞清楚这些框架和库的过程中通常是很费时和费力的,更何况有时还缺乏相应的文档帮助。
事实上,除了整个行业都广泛使用的框架和库,对于大多数的代码来说,在脱离了特定的项目和开发组环境的情况下是完全没有任何价值的。
3.3 难于控制成本
在开发实践中,设计和开发一个恰当抽象并通用的框架所花费的精力和成本可能远比一次性的解决方案要多,因为在分析重用代码所带来的好处时,很少把开发者用于接受复杂的新框架所花费的时间和代价计算在内,同时,重用的代码可能的低使用率也是增加设计重用代码成本的一个重要方面,所以实际发生的代码重用比起想象中的要少得多。
4 结束语
尽管代码重用技术不是什么通灵宝贝,然而在实际的编程中,还是得到了广泛的运用,特别是对于面向对象的Java语言而言更是如此。在本文中给出的几个策略是实现Java代码重用的行之有效的方法,而通过这些方法与面向对象编程技术进行有机结合形成的一些实例方法往往对于提高代码内聚性、降低复杂性及耦合度方面具有极其重要的作用。然而,由于重用代码技术本身的复杂性,至今还缺乏相应统一的标准和自动检索机制,因此对于新的代码重用技术的探索仍然是程序员努力的方向之一。
摘要:尽管代码重用性受到了垢病,但在Java应用开发中,代码重用技术还是得到了越来越多的软件工程师的重视,因为对于某些代码的重用不仅能够使得程序变得更加简练、清晰和易于维护,而且更重要的是可以节约软件开发的成本,提高软件生产的效率,同时还能够增加代码的可靠性和增强被重用代码与系统函数的其他部分的一致性。文章就这一问题对在Java应用开发中代码重用的优劣进行了深入分析,并提出了几个相关的重用代码的解决策略。
关键词:代码重用,接口,代码分离,内聚性,耦合度
参考文献
[1]Steven M J.设计模式Java手册[M].北京:机械工业出版社,2006.
[2]刘晓华.精通Java核心技术[M].北京:电子工业出版社,2005.
[3]耿祥义,张跃平.Java 2实用教程(第3版)[M].北京:清华大学出版社,2006.
[4]埃史尔.Java编程思想(第4版)[M].北京:机械工业出版社,2007.
[5]毛凯.基于面向方面的软件重用模式设计[J].计算机科学,2007,34(9):259-261.
[6]肖汉.基于Java平台的通用构件库的研究与设计[J].计算机工程与设计,2006,27(15):2737-2739.
[7]谢冰,张晨东.面向对象测试代码复用算法与工具[J].计算机工程与科学.2008,30(11):109-110.
[8]孟晓明.利用Include指令实现ASP页面的代码重用[J].计算机应用与软件,2004,27(7):107-108.
[9]张晓黎,吕歆.组件技术及适应性叠覆组件改造技术在提高代码重用性方面的研究[J].计算机应用研究,2004,21(5):75-77.
[10]成岳鹏,戴永成.基于面向对象的软件重用技术[J].河北工业科技,2009,26(5):434-437.
[11]周晓锋,刘馨月.基于可重用组件技术的软件开发方法[J].信息技术,2005,29(11):139-141.
java代码查错面试题 篇4
1.
abstract class Name
{
private String name;
public abstract boolean isStupidName(String name) {}
}
答案: 错,abstract method必须以分号结尾,且不带花括号。
2.
public class Something
{
void doSomething
{
private String s = “”;
int l = s.length();
}
}
答案: 错。局部变量前不能放置任何访问修饰符(private,public,和protected)。final可以用来修饰局部变量(final如同abstract和strictfp,都是非访问修饰符,strictfp只能修饰class和method而非variable)。
3.
abstract class Something
{
private abstract String doSomething ();
}
答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的,怎么可以用private把abstractmethod封锁起来呢? (同理,abstract method前不能加final)。
4.
public class Something
{
public int addOne(final int x)
{
return ++x;
}
}
答案: 错。int x被修饰成final,意味着x不能在addOne method中被修改。
5.
public class Something
{
public static void main(String[] args)
{
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o)
{
o.i++;
}
}
class Other
{
public int i;
}
答案: 正确,
在addOne method中,参数o被修饰成final。如果在addOne method里我们修改了o的`reference(比如: o = new Other();),那么如同上例这题也是错的。但这里修改的是o的member vairable(成员变量),而o的reference并没有改变。
6.
class Something
{
int i;
public void doSomething()
{
System.out.println(“i = ” + i);
}
}
答案: 正确。输出的是“i = 0”。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。int的default value是0。
7.
class Something
{
final int i;
public void doSomething()
{
System.out.println(“i = ” + i);
}
}
答案: 错。final int i 是个final的 instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为“final int i = 0;”。
8.
public class Something
{
public static void main(String[] args)
{
Something s = new Something();
System.out.println(“s.doSomething() returns ” + doSomething());
}
public String doSomething()
{
return “Do something ...”;
}
}
java源代码 篇5
1 安全体系结构
对于Java安全体系结构的分析, 我们可以通过“沙箱”模型来具体描述。所谓“沙箱”模型, 其本质主要是根据代码来源不同, 对其访问系统资源的权限进行控制。一般来说, 代码来源主要分为两种, 即本地代码和远程代码。其中, 本地代码可以访问系统中的所有资源, 而远程代码则只能访问部分系统资源。比如在JDK1.1中所引入的签名Applet概念, 此概念主要可以分为两类, 一类是有正确数字签名的Applet, 另一类是未签名的Applet。通常情况下, 前者被系统视为本地代码, 可以对系统的所有资源进行访问, 而后者则作为远程代码, 只可以访问部分资源。
从目前Java语言的发展情况来看, 主要经历了三个阶段, 即JDK1.0、JDK1.1和JDK1.2。每经历一个阶段, Java语言的安全性都会得到进一步的提升和完善。无论是哪一个阶段, Java安全的实现机制内容都是相同的, 主要包括以下四个方面: (1) Java语言是类型安全的, 并且容易使用。其中, 无论是垃圾收集, 还是内存管理, 对于安全代码的设计都有一定的帮助作用。 (2) 编译器和字节码校验器对于Java字节码的安全性具有较高要求, 只有合法的字节码, 才能够正常运行。 (3) 类装载器定义了本地的命名空间, 从而确保不被信任的Applet不能妨碍其它程序的运行。 (4) 对重要系统资源的访问由JVM调停, 并且事先通过安全管理器的检查。
从以上分析我们可以看出, Java技术的安全体系结构是较为分散的, 没有形成一个较为集中的安全系统, 对相关的安全特性的实现主要是通过动态类型检查、字节码校验和运行时间检查来完成的。
2 安全特性分析
2.1 类型安全
在Java技术的整个程序中, 想要充分实现其自身的安全性, 就必须重视类型系统的安全, 可以说, 这是实现Java安全的一个重要因素。在类型安全中, 我们需要考虑的问题主要有两个, 即类型检查和类型安全。一般来说, 在计算机的整体结构中, 任何一个区域都存有必要的Java对象, 且每个Java对象都有与其相对应的类标签, 以此来确保那个对象的类允许这个操作, 这种方法也可以称之为动态类型检查。虽然这种方法能够在一定程度上确保系统的正常运行, 但却存在着运行时间长、效率低等缺点。鉴于此, Java利用了静态类型检查代替动态类型检查。在实际应用的时候, 会仔细对相应程序进行考查, 如果确保某个标签的检查操作能够成功, 那么Java只会对其进行一次检查。反之, 如果对某个标签的检查操作是否能够成功存在不确定, 那么则会在程序载入之前就报出错误。
类型混乱也是Java系统中的一个非常严重的安全问题。一般来说, Java系统把对象视为内存中的块, 被分配的内存包含一个接一个排列起来的所有对象的数据域。一旦程序中的某个指令需要对某个对象引用的时候, 便需要有一个指向目标地址的一个指针, 我们可以将这个指针视为一个类型标签。在这种运行程序下, 我们如果想要从根本上确保Java系统的安全性, 首先需要考虑的就是指针是否被进行了恰当的标记。
2.2 语义分析
对于Java技术的语义分析, 我们可以从3个方面着手, 首先是公共变量。Java语法中定义了公共变量, 公共变量的值可被任何Java类的方法改写, 其中包括跨过命名空间并来自网络的Applet程序, 因此在公共变量中存储任何数据都有安全风险。其次是被保护成员变量。被保护成员变量能够被创造这个变量的类, 这个类所在的包以及这个类的子类中的所有成员访问。因此, 代码可以通过声明自己是某个包的成员而获得对被保护成员变量的访问权。最后是Java包。系统仅仅给Java包提供了基本的模板, 虽然命名空间表面上是分层的, Java的包模板却并不能嵌套;具有适当嵌套的模板, 程序员才能限制对安全敏感的组件的可见性。在目前的Java系统中, 仅仅是对变量的访问进行控制, 而不是控制变量的可见性。
3 安全代码开发
为了进一步提高代码开发的安全性, 在对代码进行开发的时候, 必须要严格遵守以下几项原则: (1) 初始化原则, 由于在系统运行过程中, 可以利用拷贝的方法, 对相关对象进行分配。因此, 应该在所有对象开始动作之前, 确保所有类已经被初始化。具体可考虑如下的做法: (1) 使所有的变量私有化。 (2) 给每个对象加入一个新的private布尔量, 设置为已被初始化。 (3) 让每个构造器在返回之前的最后才设置那个已被初始化的变量。 (4) 让每个非构造器方法在做任何事情之前核实已被初始化为真。 (2) 包不安全原则, Java包并不全都是封闭的, 在不同情况下, 包的封闭数量也有所不同。比如说, 在缺省的情况下, 只有少数包是封闭的, 并且只有少数的JVM允许关闭自己的包。在同一个包中, 没有加private, public或protected修饰符的类、变量和方法是可存取的。一个攻击者可以在你的包中引入一个新类, 并用这个新类来访问你想隐藏的东西。 (3) 少特权原则, 没有被签署的代码不具备任何特定的特权, 而没有特权的代码就不大可能造成危害。当然, 如果你必须签署代码, 那就把它们全部放在一个J A R文件中。这样做的目的是防止攻击者进行混合与匹配攻击。在这种攻击中, 攻击者用恶意的类把你的已签署了的一些类连接在一起, 或把你从未打算放在一起使用的已签署的类连接在一起, 然后放到一个新的Applet或库中。 (4) FINAL原则, 在Java系统中, 一旦有某个类是不属于final的, 那么系统攻击者就会尝试各种各样的方法来对其进行破坏。虽然这条原则看上去有些难以接受, 它要求你不使用继承, 而继承却是使用像Java这样的面向对象语言的主要好处之一。但要知道, 继承会给攻击者以更多的可乘之机。
4 结语
综上所述, 随着我国计算机技术发展脚步的不断加快, Java技术的应用也必然会越来越广泛。对Java的安全特性进行分析以及安全代码的开发研究也必然会成为技术开发人员的一项重要工作。由于Java的安全特性和安全机制直接关系到其安全性, 因此, 必须对其给予高度重视。
参考文献
[1]舒文曲, 蒋念平, 张宁.Java的安全特性分析及安全代码开发[J].计算机工程, 2002 (09) .
[2]陈李胜.Java2环境JAAS研究与实现[D].电子科技大学, 2005.
[3]牛婷芝.一种Java源代码安全分析系统的设计与实现[J].北京邮电大学, 2009.
java源代码 篇6
关键词:代码动态生成技术,Java,类文件,ASM,Bytecode
Java程序是借助于Java虚拟机所实现的, Java虚拟机能够消除底层硬件与操作系统的差异性, 从而创造出了一个具有统一处理能力的操作平台。Java虚拟机依据类文件来完成运算处理, 而类文件之中主要包含了数据与代码内容的处理。要想掌握好代码动态生成技术, 对于Java虚拟机的运行机制必须要具备详细的了解程度, 据此, 下文将主要就学习好这一技术所需要掌握的相关知识点, 以及在学习过程当中所存在的主要问题展开具体的讨论。
1 了解类文件格式
要想使得动态生成技术能够实现对类文件的装载与执行, 就必须要详细掌握Java类文件的正确格式规范。在标准的格式规范当中不但包含有文件开头部分, 同时还包含下列几部分内容。
1.1 类型与接口
类型名称、访问控制, 各类能够连接的接口。
1.2 数据域池
包含了这一类技术的全部数据内容, 各自的类型名称、调整限制、初始数值等。
1.3 方法域池
使其本身全部方法的总和, 其中详细概括了每种方法的名称, 运用限制、参数型号、返回值以及抛出异常、执行代码等相关属性内容
1.4类属性池
罗列出所有的属性, Java程序当中包含了多达20 多类的属性, 用户也可依据自身的实际需求而导入新的属性。
1.5 常量池
这当中总共有常量、类名、域名、方法等多类名称命名方法, 及其描述类型等属性的描述串内容。
2 运用ASM
类文件是一种二进制的文件, 其中要求相关的程序编写人员要具备有直接阅读与编程的能力, 而要培养学生在这一方面的能力, 便需要运用到一些相关的辅助类工具软件。当前这一方面的软件程序最为受到广泛应用的便是ASM软件, 相较于类似的软件内容, ASM软件更加小巧同时运行起来效率也更高, 是一种较为优秀的编程模型。其中还包含了有代码生成工具以及eclipse插件, 能够实现在友好的人机交互界面之下运行代码程序。ASM程序包含了两类API, 其中一类大致为处理XML等相关内容的SAX, 并借助于扫描文件从而推动整个事件的进程, 可通过访问者模式予以处置。
3 熟悉Bytecode
采用ASM软件能够较为快速的生成类文件内容, 这一工作机制的实现是位于JVM的底层所进行的, 因此应当尽量应用到简单内容的处理当中。对于复杂文件内容的处理还是应当采用较为高级的Java语言更加合适, 这样便能够达到较好的隔离、分装效果, 使不同的组织部件能够组合为基本单元。并在这一基础内容之上再次产生动态指令, 依据访问需求予以访问, 并完成所期望的处理目的。以上诸类指令内容均需要依据某一类既定的逻辑内容, 在实际的程序运行过程当中, 增加、调整或是删除处理目标与运算步骤, 如若在程序直接生成的过程当中存在较大的困难性, 仍然可采用Java先行编写一类程序模板, 并明确所需处理的基础框架与各个核心元素, 在实际的运行过程当中可以将此作为底层运行基础, 并在指令层级上予以简要的增添、删除亦或是替换。
4 掌握类装载机制
对于二进制类的文件必须要借助于装载机, 并装入到JVM之中方能够发挥出其最大的效用价值。一般状况下JVM必须要依据classpath来预先指定好搜索的路径, 并将其载入到现有文件之中。因此在程序运行过程当中动态生成二进制代码, 则必须要另行设法将其导入到系统之中, 方能够予以正常运用。这也就必须要掌握Java的类装载机制。
Java的类装载程序是在程序实际运行的过程当中, 依据即时变化的动态需求所装载的。其中虚拟机当中包含有数个类装载器, 分别来获取各自来源渠道的类文件内容。因而除了在启动类的装载器之外, 其他的均为抽象类的装载器, 大多数的状况之下, 数个类加载器当中运用双亲委派模型可以构成一个完成的装载体系, 从而保障类代码的唯一性。类文件由装载到具体的运用过程当中包含了载入、链接以及初始化等数个阶段过程, 其中在载入阶段当中可获取到二进制数据内容, 链接阶段可验证代码程序的合法性。学会这些内容的关键是理解Java的类装载过程和对应方法, 从而将之应用于内部已封装使用了自定义的、非常规的类装载器的复杂应用架构, 在教学过程中可根据实际情况进行选择。
5 结束语
通过对代码动态生成技术的学习, 能够促使学生更加详细的掌握JVM的内部运行机制, 以便于他们能够借助于这一技术方法来达成新的概念, 并通过语法层面来从本质上加深对这些内容的体会。通过这些知识内容的学习, 也能够使得学生快速的掌握这类在代码运行之时, 便能够予以修改的程序编写能力。在日常的教学过程当中教师还可向学生安排一些课题作业, 使得学生能够独立自主的完成程序编写, 要给予学生充分的信心鼓励, 使得学生能够更加有效的发挥想象力与创造力, 培养学生的开拓、创新精神。
参考文献
[1]董丽娟.网络超时在Java程序中的处理[J].通讯世界, 2015 (02) .
[2]周赛赛, 谭汉松.Java程序开发中的设计模式[J].企业技术开发, 2006 (03) .
[3]楚儿巴.乾坤大挪移让Java程序可以运行在更多手机上[J].数字通信, 2007 (20) .
[4]王芳, 耿祥义, 赵震.Java程序中的设计模式以及应用举例[J].电脑知识与技术 (学术交流) , 2007 (08) .
[5]王伟民.谈谈Java程序中的内存渗漏[J].浙江工业大学学报, 2003 (04) .
【java源代码】推荐阅读:
博饼小游戏java源代码10-16
源代码专业影评07-13
源代码安全测试论文10-20
图书管理系统源代码08-02
书店管理系统源代码08-11
源代码安全解决方案10-01
ASP.NET源代码论文05-16
c语言实现机票管理系统源代码09-26
代码重构06-08
分类代码06-08