开发过程需要注意的问题有下面这些:\x0d\x0a\x0d\x0a1. 服务器端必须提供输入数据正确性的验证,客户端的Javascript验证可以没有。这是基于安全性的考虑,因为Javascript是很容易被绕过的,增加客户端验证只是为了减少服务器压力、界面更加容易使用。 \x0d\x0a\x0d\x0a2. 适度使用Session,尽量不要在Session里放很大的集合对象,以免内存消耗过大,因为很多用户访问的时候会产生很多的Session。参数传递应该尽量通过Request。熟悉HTTP有助于更好的理解Session、Cookie、Request等的机制。\x0d\x0a\x0d\x0a3. 在带有分页的查询界面,尽量不要使用POST方法来传递参数,POST传递的参数在地址栏里是看不到的,刷新后会有重新提交表单的提示。使用GET方法传递参数要注意URL的长度不能超过1K。 \x0d\x0a\x0d\x0a4. 分层应该清晰,一般目前我们分为View(Jsp或FreeMarker加上Action)、Bean(Service)、DAO这么三层,即显示层、业务层、数据层。记录集ResultSet这种只能出现在DAO层中的对象不能出现在Bean(Service)层中,同样HttpServletRequest这种只能出现在View层的对象也不应出现在Bean(Service)层中。这并不是绝对的。 \x0d\x0a\x0d\x0a5. 尽量使用简单SQL,避免两表以及多表联查。多表联查会导致数据库压力大幅增加,而且不利于在内存中对部分记录进行缓存,代码的重用性也难以提高。 \x0d\x0a\x0d\x0a6. 避免在循环里执行findXXById这样的方法,不如执行一个findXXByIds这样的方法一次性把记录取到Map里。大部分有实际对象对应的表应该提供这样一个方法。 \x0d\x0a\x0d\x0a7. 如果使用最原始的jdbc编程的话需要注意资源的正确释放,在循环里new出来的Statement或者ResultSet就要在循环里关闭。 \x0d\x0a\x0d\x0a8. 在编写SQL进行查询的时候,需要能够判断这个SQL是否已经使用了索引,避免全表扫描,必要的时候增加索引。 \x0d\x0a\x0d\x0a9. 在写一个方法前,首先查看有没有相同功能或者很类似功能的方法已经有了,尤其是工具类方法,往往已经写过了,避免重复代码的产生,发现重复代码及时进行处理。如果一段代码被重复使用两遍或以上,那么可以考虑专门写个方法来放这段代码,同样多次使用的常量也应该专门定义出来。 \x0d\x0a\x0d\x0a10. 在一个方法里并不一定只能有一个return,如果已经有结果了尽早return,没必要增加嵌套的层次,那样会导致代码可读性不佳,但也不能return太多,代码看起来比较舒服就可以了。 \x0d\x0a\x0d\x0a11. 不要满足于能够熟练的编写DAO和Bean(Service)的代码,相比较而言,后台如果在成熟框架的支持下,编码是没有太大难度的,也不值得沾沾自喜,因为这是对Java研发工程师基本的要求。适当的培养一下前台的编码能力,学会使用Dreamweaver。不要轻视界面,也别认为这是界面设计的事情,界面对用户来说就是软件,学会编写CSS和调整界面对你没有坏处。 \x0d\x0a\x0d\x0a12. 非常明确Java和javascript作用的范围,明确它们能做的事情。 \x0d\x0a\x0d\x0a13. 一般很奇怪的现象都是由一些低级错误引起的,如果你查了一段时间也没有结果,那么让别人来查吧。 \x0d\x0a\x0d\x0a14. 不要用可能被修改的字段来做主键,那样会让相关记录的更新成为一个大麻烦。 \x0d\x0a\x0d\x0a15. 如果被迫使用Hibernate和jdbc混合操作数据库的话,不要用Hibernate来做复杂查询和统计。Hibernate用的不好的话,带来的便利是非常有限的。 \x0d\x0a\x0d\x0a16. 数据库中经常被读取,但是很少修改的话,应该把这样的数据读到内存中用OSCache之类的缓存起来,然后定期或者触发的去更新,有助于减少读数据库次数,提升性能。 \x0d\x0a\x0d\x0a17. 编码的时候应该注意部署环境带来的影响,这种影响包括操作系统不同带来路径的差异;应用服务器和数据库服务器之间时间的差异;外网可能部署在多台服务器上,放到Session里的对象因为需要复制所以要实现java.io.Serializable接口等。 \x0d\x0a\x0d\x0a18. 尽量不要在jsp上编写太多代码,保持jsp的整洁很重要,用Dreamweaver打开不至于一塌糊涂,根本看不出来这是个什么界面。 \x0d\x0a\x0d\x0a19. 目前我们的项目一般都使用Spring来管理数据库事务,而且一般都配置在Bean(Service)即业务层这一层,应该注意要保持事务的完整性,不要把一些应该放在一起的操作分散在Action这一层。相关的更新操作可以认为是一个事务,比如:增加一个家长,同时更新学生是否有家长的字段。 \x0d\x0a\x0d\x0a20. 在Spring的配置中,对于有些需要保持独立事务的方法操作,比如生成主键等,应该声明该方法为独立事务ROPAGATION_REQUIRES_NEW。Bean(Service)里如果抛出checked exception,事务默认是不会回滚的,需要加以声明,比如PROPAGATION_REQUIRED,-PassportException。 \x0d\x0a\x0d\x0a21. 在一个Bean(Service)中引用其他Bean(Service)的时候尽量引用Bean(Service),而不是DAO。因为其他的Bean(Service)往往封装DAO的操作后,又做了进一步的完善,比如增加校验等,所以应该重用这些方法,而不必要去引用DAO的方法来重写这些操作。 \x0d\x0a\x0d\x0a22. 至少在Bean(Service)的接口定义上增加注释,方便他人引用你写的方法。 \x0d\x0a\x0d\x0a23. 好好利用集合框架里的Map、List、Set。尤其是HashMap、ArrayList、HashSet用的最多,这些类是多条数据操作的基础,它们都不是线程安全的。 \x0d\x0a\x0d\x0a24. 现在跑的快的页面,随着数据量的增加,可能会变的很慢,所以应该意识到页面可能变慢的原因,而不是现在看起来很快。影响速度的大部分原因是对数据库的压力太大了,在java代码执行上花费很多时间的情况是不常见的。 \x0d\x0a\x0d\x0a25. 避免不必要的跳转,如果页面执行的足够快,那么中间的载入进度提示页是不必要的,那样会让用户觉得闪烁。 \x0d\x0a\x0d\x0a26. 注意页面的文件大小,并不是每个用户的带宽都是非常理想的,文件小一点,速度快一点,总是感觉更好一点。 \x0d\x0a\x0d\x0a27. 不要去修改用户的浏览器,比如隐藏他们的地址栏、菜单、右键菜单等,这可能会引起部分用户的反感。尽量不要使用弹出窗口,可能会被拦截。 \x0d\x0a\x0d\x0a28. 网站的权限控制至少应该保证有访问权限的用户才能访问页面,通过隐藏链接之类的方法是很不安全的,用户看不见了并不表示安全了。权限的控制尽量使用框架里的拦截器这样的机制,而不是把权限控制代码写的到处都是。过滤器不宜过多的使用,不仅因为过滤器的作用范围很难控制,而且容易引起页面执行效果的混乱,错误不易排查。 \x0d\x0a\x0d\x0a29. 页面里大部分情况使用相对路径,保持Action路径层次和页面一致,这样应用就可以发布在各种目录下。
成都创新互联主营钦南网站建设的网络公司,主营网站建设方案,成都app软件开发公司,钦南h5重庆小程序开发搭建,钦南网站营销推广欢迎钦南等地区企业咨询
以下从技术角度就常见的保护措施 和常用工具来看看如何有效保护java代码:1. 将java包装成exe 特点:将jar包装成可执行文件,便于使用,但对java程序没有任何保护。不要以为生成了exe就和普通可执行文件效果一样了。这些包装成exe的程序运行时都会将jar文件释放到临时目录,很容易获取。常用的工具有exe4j、jsmooth、NativeJ等等。jsmooth生成的exe运行时临时目录在exe所在目录中或是用户临时目录 中;exe4j生成的exe运行时临时目录在用户临时目录中;NativeJ生成的exe直接用winrar打开,然后用zip格式修复成一个jar文件,就得到了原文件。如果只是为了使用和发布方便,不需要保护java代码,使用这些工具是很好的选择。2. java混淆器特点:使用一种或多种处理方式将class文件、java源代码进行混淆处理后生成新的class,使混淆后的代码不易被反编译,而反编译后的代码难以阅 读和理解。这类混淆器工具很多,而且也很有成效。缺点:虽然混淆的代码反编译后不易读懂,但对于有经验的人或是多花些时间,还是能找到或计算出你代码中隐藏的敏感内容,而且在很多应用中不是全部代码都能混淆的,往往一些关键的库、类名、方法名、变量名等因使用要求的限制反而还不能混淆。3. 隔离java程序到服务端特点:把java程序放到服务端,让用户不能访问到class文件和相关配套文件,客户端只通过接口访问。这种方式在客户/服务模式的应用中能较好地保护java代码。缺点是:必须是客户/服务模式,这种特点限制了此种方式的使用范围;客户端因为逻辑的暴露始终是较为薄弱的环节,所以访问接口时一般都需要安全性认证。4. java加密保护特点:自定义ClassLoader,将class文件和相关文件加密,运行时由此ClassLoader解密相关文件并装载类,要起到保护作用必须自定 义本地代码执行器将自定义ClassLoader和加密解密的相关类和配套文件也保护起来。此种方式能很有效地保护java代码。缺点:可以通过替换JRE包中与类装载相关的java类或虚拟机动态库截获java字节码。 jar2exe属于这类工具。5. 提前编译技术(AOT) 特点:将java代码静态编译成本地机器码,脱离通用JRE。此种方式能够非常有效地保护java代码,且程序启动比通用JVM快一点。具有代表性的是GNU的gcj,可以做到对java代码完全提前编译,但gcj存在诸多局限性,如:对JRE 5不能完整支持、不支持JRE 6及以后的版本。由于java平台的复杂性,做到能及时支持最新java版本和JRE的完全提前编译是非常困难的,所以这类工具往往采取灵活方式,该用即时编译的地方还是 要用,成为提前编译和即时编译的混合体。缺点:由于与通用JRE的差异和java运用中的复杂性,并非java程序中的所有jar都能得到完全的保护;只能使用此种工具提供的一个运行环境,如果工具更新滞后或你需要特定版本的JRE,有可能得不到此种工具的支持。 Excelsior JET属于这类工具。6. 使用jni方式保护特点:将敏感的方法和数据通过jni方式处理。此种方式和“隔离java程序到服务端”有些类似,可以看作把需要保护的代码和数据“隔离”到动态库中,不同的是可以在单机程序中运用。缺点和上述“隔离java程序到服务端”类似。7. 不脱离JRE的综合方式保护特点:非提前编译,不脱离JRE,采用多种软保护方式,从多方面防止java程序被窃取。此种方式由于采取了多种保护措施,比如自定义执行器和装载器、加密、JNI、安全性检测、生成可执行文件等等,使保护力度大大增强,同样能够非常有效地保护java代码。缺点:由于jar文件存在方式的改变和java运用中的复杂性,并非java程序中的所有jar都能得到完全的保护;很有可能并不支持所有的JRE版本。 JXMaker属于此类工具。8. 用加密锁硬件保护特点:使用与硬件相关的专用程序将java虚拟机启动程序加壳,将虚拟机配套文件和java程序加密,启动的是加壳程序,由加壳程序建立一个与硬件相关的 受保护的运行环境,为了加强安全性可以和加密锁内植入的程序互动。此种方式与以上“不脱离JRE的综合方式保护”相似,只是使用了专用硬件设备,也能很好地保护java代码。缺点:有人认为加密锁用户使用上不太方便,且每个安装需要附带一个。从以上描述中我们可以看出:1. 各种保护方式都有其优缺点,应根据实际选用2. 要更好地保护java代码应该使用综合的保护措施3. 单机环境中要真正有效保护java代码,必须要有本地代码程序配合当然,安全都是相对的,一方面看你的保护措施和使用的工具能达到的程度,一方面看黑客的意愿和能力,不能只从技术上保护知识产权。总之,在java 代码保护方面可以采取各种可能的方式,不可拘泥于那些条条框框。
Java语言包含三种核心机制:Java 虚拟机、垃圾收集机制和代码安全检测。
1、Java 虚拟机(Java Virtual Machine,JVM)
在一台计算机上由软件或硬件模拟的计算机。Java虚拟机读取并处理经编译过的平台无关的字节码class文件。
2、垃圾收集机制(Garbage collection)
在C/C++ 等语言中,由程序员负责回收无用内存。Java语言解除了程序员回收无用内存空间的责任。它提供一种系统级线程跟踪存储空间的分配情况。并在JVM的空闲时,检查并释放那些可被释放的存储器空间。垃圾收集在Java程序运行过程中自动进行,程序员无法精确控制和干预。
3、代码安全性检测(Code Security)
Java执行代码的时候,由JVM对运行的代码进行安全性检测,当进行一些非法操作的时候,比如修改一些系统设置的时候,JVM会发出警告。
Java是一种跨平台的 解释型语言 Java 源代码编译中间 字节码 存储于class文件中 Class文件是一种字节码形式的中间代码 该字节码中包括了很多源代码的信息 例如变量名 方法名等 因此 Java中间代码的反编译就变得非常容易 目前市场上有许多免费的 商用的反编译软件 都能够生成高质量的反编译后的源代码 所以 对开发人员来说 如何保护Java程序就变成了一个非常重要的挑战 本文首先讨论了保护Java程序的基本方法 然后对代码混淆问题进行深入研究 最后结合一个实际的应用程序 分析如何在实践中保护Java程序 反编译成为保护Java程序的最大挑战 通常C C++等编程语言开发的程序都被编译成目标代码 这些目标代码都是本机器的二进制可执行代码 通常所有的源文件被编译 链接成一个可执行文件 在这些可执行文件中 编译器删除了程序中的变量名称 方法名称等信息 这些信息往往是由内存地址表示 例如如果需要使用一个变量 往往是通过这个变量的地址来访问的 因此 反编译这些本地的目标代码就是非常困难的 Java语言的出现 使得反编译变得非常容易而有效 原因如下 由于跨平台的需求 Java的指令集比较简单而通用 较容易得出程序的语义信息 Java编译器将每一个类编译成一个单独的文件 这也简化了反编译的工作 Java 的Class文件中 仍然保留所有的方法名称 变量名称 并且通过这些名称来访问变量和方法 这些符号往往带有许多语义信息 由于Java程序自身的特点 对于不经过处理的Java程序反编译的效果非常好 目前 市场上有许多Java的反编译工具 有免费的 也有商业使用的 还有的是开放源代码的 这些工具的反编译速度和效果都非常不错 好的反编译软件 能够反编译出非常接近源代码的程序 因此 通过反编译器 黑客能够对这些程序进行更改 或者复用其中的程序 因此 如何保护Java程序不被反编译 是非常重要的一个问题 常用的保护技术 由于Java字节码的抽象级别较高 因此它们较容易被反编译 本节介绍了几种常用的方法 用于保护Java字节码不被反编译 通常 这些方法不能够绝对防止程序被反编译 而是加大反编译的难度而已 因为这些方法都有自己的使用环境和弱点 隔离Java程序 最简单的方法就是让用户不能够访问到Java Class程序 这种方法是最根本的方法 具体实现有多种方式 例如 开发人员可以将关键的Java Class放在服务器端 客户端通过访问服务器的相关接口来获得服务 而不是直接访问Class文件 这样黑客就没有办法反编译Class文件 目前 通过接口提供服务的标准和协议也越来越多 例如 HTTP Web Service RPC等 但是有很多应用都不适合这种保护方式 例如对于单机运行的程序就无法隔离Java程序 这种保护方式见图 所示 图 隔离Java程序示意图 对Class文件进行加密 为了防止Class文件被直接反编译 许多开发人员将一些关键的Class文件进行加密 例如对注册码 序列号管理相关的类等 在使用这些被加密的类之前 程序首先需要对这些类进行解密 而后再将这些类装载到JVM当中 这些类的解密可以由硬件完成 也可以使用软件完成 在实现时 开发人员往往通过自定义ClassLoader类来完成加密类的装载(注意由于安全性的原因 Applet不能够支持自定义的ClassLoader) 自定义的ClassLoader首先找到加密的类 而后进行解密 最后将解密后的类装载到JVM当中 在这种保护方式中 自定义的ClassLoader是非常关键的类 由于它本身不是被加密的 因此它可能成为黑客最先攻击的目标 如果相关的解密密钥和算法被攻克 那么被加密的类也很容易被解密 这种保护方式示意图见图 图 对Class文件进行加密示意图 转换成本地代码 将程序转换成本地代码也是一种防止反编译的有效方法 因为本地代码往往难以被反编译 开发人员可以选择将整个应用程序转换成本地代码 也可以选择关键模块转换 如果仅仅转换关键部分模块 Java程序在使用这些模块时 需要使用JNI技术进行调用 当然 在使用这种技术保护Java程序的同时 也牺牲了Java的跨平台特性 对于不同的平台 我们需要维护不同版本的本地代码 这将加重软件支持和维护的工作 不过对于一些关键的模块 有时这种方案往往是必要的 为了保证这些本地代码不被修改和替代 通常需要对这些代码进行数字签名 在使用这些本地代码之前 往往需要对这些本地代码进行认证 确保这些代码没有被黑客更改 如果签名检查通过 则调用相关JNI方法 这种保护方式示意图见图 代码混淆 图 转换成本地代码示意图 代码混淆是对Class文件进行重新组织和处理 使得处理后的代码与处理前代码完成相同的功能(语义) 但是混淆后的代码很难被反编译 即反编译后得出的代码是非常难懂 晦涩的 因此反编译人员很难得出程序的真正语义 从理论上来说 黑客如果有足够的时间 被混淆的代码仍然可能被破解 甚至目前有些人正在研制反混淆的工具 但是从实际情况来看 由于混淆技术的多元化发展 混淆理论的成熟 经过混淆的Java代码还是能够很好地防止反编译 下面我们会详细介绍混淆技术 因为混淆是一种保护Java程序的重要技术 图 是代码混淆的示意图 图 代码混淆示意图 几种技术的总结 以上几种技术都有不同的应用环境 各自都有自己的弱点 表 是相关特点的比较 混淆技术介绍 表 不同保护技术比较表 到目前为止 对于Java程序的保护 混淆技术还是最基本的保护方法 Java混淆工具也非常多 包括商业的 免费的 开放源代码的 Sun公司也提供了自己的混淆工具 它们大多都是对Class文件进行混淆处理 也有少量工具首先对源代码进行处理 然后再对Class进行处理 这样加大了混淆处理的力度 目前 商业上比较成功的混淆工具包括JProof公司的 stBarrier系列 Eastridge公司的JShrink和的SourceGuard等 主要的混淆技术按照混淆目标可以进行如下分类 它们分别为符号混淆(Lexical Obfuscation) 数据混淆(Data Obfuscation) 控制混淆(Control Obfuscation) 预防性混淆(Prevent Transformation) 符号混淆 在Class中存在许多与程序执行本身无关的信息 例如方法名称 变量名称 这些符号的名称往往带有一定的含义 例如某个方法名为getKeyLength() 那么这个方法很可能就是用来返回Key的长度 符号混淆就是将这些信息打乱 把这些信息变成无任何意义的表示 例如将所有的变量从vairant_ 开始编号 对于所有的方法从method_ 开始编号 这将对反编译带来一定的困难 对于私有函数 局部变量 通常可以改变它们的符号 而不影响程序的运行 但是对于一些接口名称 公有函数 成员变量 如果有其它外部模块需要引用这些符号 我们往往需要保留这些名称 否则外部模块找不到这些名称的方法和变量 因此 多数的混淆工具对于符号混淆 都提供了丰富的选项 让用户选择是否 如何进行符号混淆 数据混淆 图 改变数据访问 数据混淆是对程序使用的数据进行混淆 混淆的方法也有多种 主要可以分为改变数据存储及编码(Store and Encode Transform) 改变数据访问(Access Transform) 改变数据存储和编码可以打乱程序使用的数据存储方式 例如将一个有 个成员的数组 拆开为 个变量 并且打乱这些变量的名字 将一个两维数组转化为一个一维数组等 对于一些复杂的数据结构 我们将打乱它的数据结构 例如用多个类代替一个复杂的类等 另外一种方式是改变数据访问 例如访问数组的下标时 我们可以进行一定的计算 图 就是一个例子 在实践混淆处理中 这两种方法通常是综合使用的 在打乱数据存储的同时 也打乱数据访问的方式 经过对数据混淆 程序的语义变得复杂了 这样增大了反编译的难度 控制混淆 控制混淆就是对程序的控制流进行混淆 使得程序的控制流更加难以反编译 通常控制流的改变需要增加一些额外的计算和控制流 因此在性能上会给程序带来一定的负面影响 有时 需要在程序的性能和混淆程度之间进行权衡 控制混淆的技术最为复杂 技巧也最多 这些技术可以分为如下几类 增加混淆控制 通过增加额外的 复杂的控制流 可以将程序原来的语义隐藏起来 例如 对于按次序执行的两个语句A B 我们可以增加一个控制条件 以决定B的执行 通过这种方式加大反汇编的难度 但是所有的干扰控制都不应该影响B的执行 图 就给出三种方式 为这个例子增加混淆控制 图 增加混淆控制的三种方式 控制流重组 重组控制流也是重要的混淆方法 例如 程序调用一个方法 在混淆后 可以将该方法代码嵌入到调用程序当中 反过来 程 lishixinzhi/Article/program/Java/JSP/201311/19576