精华内容
参与话题
问答
  • 本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议(英文版)》一书中的第2章,第2.6节,作者:【美】Fred Long(弗雷德•朗),Dhruv Mohindra(德鲁•莫欣达), Robert C. Seacord(罗伯特 C.西科德)...

    本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议(英文版)》一书中的第2章,第2.6节,作者:【美】Fred Long(弗雷德•朗),Dhruv Mohindra(德鲁•莫欣达), Robert C. Seacord(罗伯特 C.西科德),Dean F.Sutherland(迪恩 F.萨瑟兰),David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

    2.6 将程序编译为class文件

    在运行Java程序之前,必须先编译它。在编译程序时,输入到计算机中的程序指令被转换为计算机可以更容易理解的一种形式。

    在NetBeans中,程序在保存时会自动进行编译。如果你输入程序清单2.2中的指令,则该程序将顺利通过编译。

    该程序在编译之后生成一个新的文件,名为Saluton.class。所有的Java程序都将编译为类(class)文件,且其文件后缀名为.class。Java程序也可以由协同工作的多个类文件组成,但是对于Saluton这样简单的程序来说,只需要一个类文件。

    编译器将Java源代码转换为字节码,这是一种Java虚拟机(JVM)可以运行的格式。

    只有Java程序在编译出现错误时,Java编译器才会有提示。如果你成功地编译完了一个程序,期间没有任何错误,则Java编译器不会有任何“动静”。这有点虎头蛇尾。当我在刚开始学习Java编程时,我曾经希望在编译取得成功时,能够响起庆祝的号角。

    展开全文
  • java平台本身的安全性 安全第一,不要写聪明的代码 在代码设计之初就考虑安全性 避免重复的代码 限制权限 构建可信边界 封装 写文档 简介 作为一个程序员,只是写出好用的代码是不够的,我们还需要考虑到程序的安全...

    目录

    简介
    java平台本身的安全性
    安全第一,不要写聪明的代码
    在代码设计之初就考虑安全性
    避免重复的代码
    限制权限
    构建可信边界
    封装
    写文档
    

    简介

    作为一个程序员,只是写出好用的代码是不够的,我们还需要考虑到程序的安全性。在这个不能跟陌生人说话世界,扶老奶奶过马路都是一件很困难的事情。那么对于程序员来说,尤其是对于开发那种对外可以公开访问的网站的程序员,要承受的压力会大很多。

    任何人都可以访问我们的系统,也就意味着如果我们的系统不够健壮,或者有些漏洞,恶意攻击者就会破门而入,将我们辛辛苦苦写的程序蹂躏的体无完肤。

    所以,安全很重要,今天本文将会探讨一下java中的安全编码指南。
    java平台本身的安全性

    作为一个强类型语言,java平台本身已经尽可能的考虑到了安全性的,为我们屏蔽了大多数安全性的细节。

    比如可以为不同级别权限的代码提供受限的执行环境。 java程序是类型安全的,并且在运行时提供了自动内存管理和数组边界检查,Java会尽可能的及早发现程序中的问题,从而使Java程序具有很高的抵抗堆栈破坏的能力。

    尽管Java安全体系结构在许多情况下可以帮助保护用户和系统免受恶意代码或行为不当的攻击,但它无法防御可信任代码中发生的错误。也就说如果是用户本身代码的漏洞,java安全体系是无法进行判断的。

    这些错误可能会绕过java本身的安全体系结构。在严重的情况下,可能会执行本地程序或禁用Java安全性。从而会被用来从计算机和Intranet窃取机密数据,滥用系统资源,阻止计算机的有用操作,协助进一步的攻击以及许多其他恶意活动。

    所以,最大的安全在程序员本身,不管外部机制如何强大,如果核心的程序员出了问题,那么一切都将归于虚无。

    接下来,我们看下java程序员应该遵循一些什么行为准则,来保证程序的安全性呢?
    安全第一,不要写聪明的代码

    我们可能会在很多教科书甚至是JDK的源代码中,看到很多让人惊叹的代码写法,如果你真的真的明白你在做什么,那么这样写没什么问题。但是很多情况下我们并不是很了解这样写的原理,甚至不知道这样写会出现什么样的问题。

    并且现代系统是一个多人协作的过程,如果你写了这样的聪明代码,很有可能别人看不懂,最后导致未知的系统问题。

    给大家举个例子:

    😦){😐:&};:

    上面是一个shell下面的fork炸弹,如果你在shell下面运行上面的代码,几秒之后系统就会宕机或者运行出错。

    怎么分析上面的代码呢?我们把代码展开:

    😦)
    {
    😐:&
    };
    :

    还是不明白? 我们把:替换成函数名:

    fork()
    {
    fork|fork&
    };
    fork

    上面的代码就是无限的fork进程,通过几何级数的增长,最后导致程序崩溃。

    java设计的很多大神把他们跳跃般的思想写到了JDK源代码里面,大神们的思想经过了千锤百炼,并且JDK是Java的核心,里面的代码再优化也不为过。

    但是现在硬件技术的发展,代码级别的优化可能作用已经比较少了。为了避免出现不可知的安全问题,还是建议大家编写一眼就能看出逻辑的代码。虽然可能不是那么快,但是安全性有了保证。除非你真的知道你在做什么。
    在代码设计之初就考虑安全性

    安全性应该是一个在编写代码过程中非常重要的标准,我们在设计代码的时候就应该考虑到相关的安全性问题,否则后面重构起来会非常费事。

    举个例子:

        public final class SensitiveClass {
    
            private final Behavior behavior;
    
            // Hide constructor.
            private SensitiveClass(Behavior behavior) {
                this.behavior = behavior;
            }
    
            // Guarded construction.
            public static SensitiveClass newSensitiveClass(Behavior behavior) {
                // ... validate any arguments ...
    
                // ... perform security checks ...
    
                return new SensitiveClass(behavior);
            }
        }
    

    上面的例子中我们使用了final关键字来防止我们的某些关键类被继承扩展。因为没有扩展性,所以安全性判断会更加容易。

    同时,java提供了SecurityManager和一系列的Permission类,通过合理的配置,我们可以有效的控制java程序的访问权限。
    避免重复的代码

    和重复代码相关的一个关键词就是重构。为什么会出现重复代码呢?

    很简单,最开始我们在实现一个功能的时候写了一段代码逻辑。结果后面还有一个方法要使用这段代码逻辑。然后我们为了图方便,就把代码逻辑拷贝过去了。

    看起来问题好像解决了。但是一旦这段业务逻辑要修改,那可就是非常麻烦的一件事情。因为我们需要找到程序中所有出现这段代码的地方,然后一个一个的修改。

    为什么不把这段代码提取出来,做成一个单独的方法来供其他的方法调用呢?这样即使后面需要修改,也只用修改一处地方即可。

    在现实的工作中,我们经常会遇到这种问题,尤其是那种年久失修的代码,大家都不敢修改,因为牵一发而动全身。往往是修改了这边忘记了那边,最后导致bug重重。
    限制权限

    JDK专门提供了一个SecurityManager类,来显示的对安全性进行控制,我们看下SecurityManager是怎么使用的:

    SecurityManager security = System.getSecurityManager();
    if (security != null) {
    security.checkXXX(argument, …);
    }
    http://www.szfyss.com
    SecurityManager提供了一系列的check方法,来对权限进行控制。

    权限分为以下类别:文件、套接字、网络、安全性、运行时、属性、AWT、反射和可序列化。管理各种权限类别的类是 :
      java.io.FilePermission、
      java.net.SocketPermission、
      java.net.NetPermission、
      java.security.SecurityPermission、
      java.lang.RuntimePermission、
      java.util.PropertyPermission、
      java.awt.AWTPermission、
      java.lang.reflect.ReflectPermission
      java.io.SerializablePermission

    JDK本身已经使用了很多这些权限控制的代码。比如说我们最常用的File:

    public boolean canRead() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_READ);
    }
    

    http://www.tzsumei.com
    上面是File类的canRead方法,我们会首先去判断是否配置了SecurityManager,如果配置了,则去检查是否可以read。

    如果我们在写代码中,遇到文件、套接字、网络、安全性、运行时、属性、AWT、反射和可序列化相关的操作时,也可以考虑使用SecurityManager来进行细粒度的权限控制。
    构建可信边界

    什么是可信边界呢?边界主要起拦截作用,边界里边的我们可以信任,边界外边的我们就不能信任了。

    对于不能信任的外边界请求,我们需要进行足够的安全访问控制。

    比如说web客户端来访问web服务器。web客户端是在全球各地的,各种环境都有,并且是不可控的,所以web客户端访问web服务器端的请求需要进行额外的安全控制。

    而web服务器访问业务服务器又是不同的,因为web服务器是我们自己控制的,所以安全程度相对较高,我们需要针对不同的可信边界做不同的控制。http://www.zzgmzs.com
    封装

    封装(Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。

    封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。通过对接口进行访问控制,可以严格的包含类中的数据和方法。

    并且封装可以减少耦合,并且隐藏实现细节。
    写文档

    最后一项也是非常非常重要的一项就是写文档。为什么接别人的老项目那么痛苦,为什么读源代码那么困难。根本的原因就是没有写文档。

    如果不写文档,可能你自己写的代码过一段时间之后也不知道为什么当时这样写了。

    展开全文
  • Java编码指南(7)

    2011-07-28 11:19:06
    5.5 数值规范【JAVA-24】 进行无误差或大数计算时,使用BigDecimal Class【推荐】说明·原因浮点数运算是用于科学技术计算的,会发生误差。与此相比,Class“BigDecimal”,是用字符串计算数值的,适合用于金额等...
     

    5.5     数值规范

    【JAVA-24】   进行无误差或大数计算时,使用BigDecimal Class【推荐】

    说明·原因

    浮点数运算是用于科学技术计算的,会发生误差。与此相比,Class“BigDecimal”,是用字符串计算数值的,适合用于金额等的正确的计算。使用BigDecimal,可以保证生成Instance时指定的位数上的精度。

     

    【JAVA-25】   不转成低精度的原语型【注意】

    说明·原因

    表示数值的原语型的变量中,定义了数值的精度。如果将高精度的变量转换成低精度的型,其值就会变更为转型后的精度。因此,计算中可能会出现误差。

    double doubleType = 2.75;

    int intType = (int)doubleType; // 将double转成int型 //错误

     

    5.6     集合规范

    【JAVA-26】   使用Java2之后的集合类【推荐】

    说明·原因

    是否使用了Vector Class、Hashtable Class、Enumeration Class?如果没有使用这些的特别理由,那么为了统一Interface,请使用List(ArrayList Class)、Map(HashMap Class)、Iterator来代替这些。通过使用List等的Interface,可以利用JDK1.2中整理的易懂的Method。另外,因Interface的特性,变更实现Class时可以不变更调用方。

    Vector sampleVector = new Vector(); //错误

    List sampleList = new ArrayList(); //正确

     

    【JAVA-27】   利用只接受特定型的Object的集合类【推荐】

    说明·原因

    在集合中只保存某个特定型的Object时,针对只处理特定型Object的集合类,有新定义的方法。比如,自己定义只保存String的集合。

    定义这样的集合类的好处如下:

    l  不会错误保存不同型的Object,因此不会发生ClassCastException;

    l  从集合取出Object时,不用一个一个地转型(也不需要instanceof的Check Logic)。

    基于上述原因,可减少发生BUG的可能性,代码也变得简单,进而可提高代码的可读性。

    下面的Class是只处理String Object的HashMap的例子:

    public class StringHashMap {

        private HashMap map = new HashMap();

        public void put( String key, String value ){

            map.put( key, value );

        }

        public String get( String key ){

            return (String)map.get(key);

        }

    }

     

    5.7     Stream规范

    【JAVA-28】   利用处理Stream的API时,在finally Block中进行后处理【注意】

    说明·原因

    为避免内存泄漏,Stream的Close是必须的。即使中途发生了异常,也必须Close,因此请在finally Block中描述close() Method。

    try {

        BufferedReader reader = new BufferedReader(new FileReader(file));

        reader.read();

        reader.close(); // 错误

    } catch (FileNotFoundException fnfe) {

        fnfe.printStackTrace();

    } catch (IOException ioe) {

        ioe.printStackTrace();

    }

    BufferedReader reader = null;

    try {

        reader = new BufferedReader(new FileReader(file));

        reader.read();

    } catch (FileNotFoundException fnfe) {

        fnfe.printStackTrace();

    } catch (IOException ioe1) {

        ioe1.printStackTrace();

    } finally {

        try{

            reader.close(); // 正确

        }catch(IOException ioe2){

            ioe2.printStackTrace();

        }

    }

     

    【JAVA-29】    ObjectOutputStream中利用reset()【推荐】

    说明·原因

    在使用ObjectOutputStream Object的Method中,请适当调用reset()。关于ObjectOutputStream Class,从其功能上来看,它会始终保持对写入的所有的Object的应用,直至调用reset()为止。在调用reset() Method之前,这些Object不会被GC回收。不调用reset() Method,而通过ObjectOutputStream Object写出了很多个Object时,可能会发生OutOfMemoryError。

    public class BadSample {

    public void writeToStream(Object input)throws IOException {

    ObjectOutputStream stream = new ObjectOutputStream(

    new FileOutputStream("output"));

    stream.writeObject(input); // 错误

      }

    }

     

    public class FixedSample {

    public void writeToStream(Object input)throws IOException {

    ObjectOutputStream stream = new ObjectOutputStream(

    new FileOutputStream("output"));

    stream.writeObject(input);

    stream.reset();// 正确

      }

    }

     

    5.8     异常规范

    【JAVA-30】   生成Exception Class的Object后不抛出【注意】

    说明·原因

    Exception Class是所有的异常的超类。将Exception Class的Instance作为异常来接受的代码中,对其异常的种类及处理,将不能利用Polymorphism(多态性)。请务必抛出合适的Subclass的Object。

    public void badSampleMethod() throws Exception { // 错误

    throw new Exception(); // 错误

    }

    public void fixedSampleMethod () throws NoSuchMethodException { // 正确

    throw new NoSuchMethodException ();// 正确

    }

     

    【JAVA-31】   catch Block中必须进行处理【推荐】

    说明·原因

    不要使catch Block为空,一定要对异常进行处理。正是为了处理异常才Catch的。什么也不做的话会发生新的BUG。即使处理不了,也要进行能确认发生了异常的动作,如输出到LOG。

    try{

    reader.close();

    }catch(IOException ioe2){ //错误

    }

    try{

    reader.close();

    }catch(IOException ioe2){

    ioe2.printStackTrace(); //正确

    }

     

    【JAVA-32】   不继承ErrorThrowable Class【注意】

    说明·原因

    请不要定义Error Class的Subclass。Error Class表示在Application中不应Catch的重大的问题。因此,在Application中不能定义Error Class的Subclass。在Application定义的异常继承Exception Class。另外,不能定义Throwable的Subclass。Throwable Class是Exception和Error的超类。如果此Class继承Application的异常,那么Error和异常的意义就会变得模糊。Error Class,如上所述是不应该在Application继承的。同样,Application不应该继承Thorwable Class。Application中定义的异常继承Exception Class。

    public class BadSampleException extends Error { // 错误

    }

    public class AnotherBadSampleException extends Throwable { // 错误

    }

    public class FixedSampleException extends Exception { // 正确

    }

     

    展开全文
  • 高质量Java编码指南

    2012-02-04 14:33:58
    核心思想依然是《Effective Java》里面说:“好”的程序,才会跑的更快! 1. 结构清晰:善用局部变量,小方法。 2. 不滥用异常机制。 3. 多重循环,拆分成小方法,循环边界尽量固定。 4. 更小的锁。 5. 注意...
    核心思想依然是《Effective Java》里面说:“好”的程序,才会跑的更快!

    1. 结构清晰:善用局部变量,小方法。
    2. 不滥用异常机制。
    3. 多重循环,拆分成小方法,循环边界尽量固定。
    4. 更小的锁。
    5. 注意大资源的合理缓存与释放。
    6. 多用接口,少用反射。


    原因分析:
    局部变量的访问速度远比实例变量/静态变量快
    小方法比大方法易于优化
    如果在正常的执行路径上抛异常很可能极大影响性能
    Object.getClass()很快,其它操作相对会慢许多
    展开全文
  • Java编码指南(1)

    2011-07-28 11:11:31
    1 命名规范1.1 Package命名规范【JAVA-1】 Package名要使用小写字,中间用“.”分割【规定】说明·原因如无特殊规定,请将Package名统一成小写字。这是Java的一般规则。例package cn.co.AAA.BBB;
  • Alibaba Java Coding Guidelines插件 选择 Android studio - Preferences - Plugins - 搜索Alibaba Java Coding Guidelines 重启AS..
  • java安全编码指南之:输入注入injection

    千次阅读 热门讨论 2020-10-12 09:03:44
    注入问题是安全中一个非常常见的问题,今天我们来探讨一下java中的SQL注入和XML注入的防范。
  • 本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.5节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F....
  • 这些Java编码指南的应用将会带来更健壮、更能抵御攻击的系统。这些编码指南覆盖范围广泛,适用于大多数基于Java编写的运行在不同设备上的产品,这些设备包括电脑、游戏机、手机、平板电脑、家用电器和汽车电子设备。...
  • Java编码指南(6)

    2011-07-28 11:18:07
    5.2 修饰符规范【JAVA-8】 使用恰当的权限来声明【推荐】说明·原因充分理解private、public等访问修饰符的意义,并用恰当的权限来声明Class、Method、变量、变量、常量等。 【JAVA-9】 对于不想继承的Class,...
  • 本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.7节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F....
  • java安全编码指南之:基础篇

    千次阅读 2020-08-25 14:48:27
    简介:作为一个程序员,只是写出好用的代码是不够的,我们还需要考虑到程序的...所以,安全很重要,今天本文将会探讨一下java中的安全编码指南。 简介作为一个程序员,只是写出好用的代码是不够的,我们还需要考虑到
  • Java编码指南(3)

    2011-07-28 11:12:48
    1 书写格式规范【JAVA-1】 不使用Tab,而是使用4个空格代替一个Tab【规定】说明·原因如果缩进时同时使用了空白字符和Tab,会因编辑器的设定的不同而对不齐缩进,进而降低代码的可读性。请不要使用Tab,而是使用4...

空空如也

1 2 3 4 5 ... 20
收藏数 35,372
精华内容 14,148
关键字:

java编码指南

java 订阅