代码之家  ›  专栏  ›  技术社区  ›  Andres

Java的“最终”关键字是否确实提高了安全性?

  •  19
  • Andres  · 技术社区  · 14 年前

    当有 many reasons to use the 'final' keyword in Java ,我反复听到的一个问题是它使您的代码更加安全。虽然这在这个微不足道的案例中似乎很有意义:

    public class Password
    {
        public final String passwordHash;
        ...
    }
    

    对于最后一个关键字,您希望没有恶意代码能够更改变量passwordhash。然而, using reflection 可以更改密码哈希字段的最终修饰符。

    那么“最终”是否提供了真正的安全性,或者只是安慰剂?

    编辑: 有一些非常有趣的讨论,我希望我能接受不止一个答案。感谢大家的意见。

    12 回复  |  直到 9 年前
        1
  •  37
  •   starblue    14 年前

    从“抵御攻击”的意义上说,这不是“安全”;更像是“更难误入歧途”。

    我更喜欢“安全”这个词;我觉得它更像是预防事故,而不是恶意。

        2
  •  10
  •   Andrew Hare    14 年前

    爪哇 final 关键字不用于这种安全性。它不能代替通常需要密码解决方案的方案。

    在这些讨论中,“安全性”通常指的是安全对象模型的概念——也就是说,一个对象模型不能被消费者操纵,以达到类的原始作者不希望达到的目的。

        3
  •  8
  •   Uri    14 年前

    我不确定是否要依赖语言构造来增加系统中的安全性。

    我不认为让一个字段成为最终版本会增加对恶意攻击的安全性(更可能防止错误,当然还有线程问题)。唯一的“真正形式”的安全性是,如果有最后一个常量字段,它可能在编译时被内联,因此在运行时更改其值不会产生影响。

    在继承的背景下,我更多地听说了最终和安全。通过使一个类成为最终类,您可以防止有人对它进行子类化,并接触或覆盖它的受保护成员,但我再次使用它来避免错误,而不是防止威胁。

        4
  •  4
  •   Tom Hawtin - tackline    14 年前

    防范什么?

    在移动代码方面(可以在系统之间移动的代码-小程序、MIDlet、WebStart、RMI/JINI等),它非常重要。应用于类,并在较小程度上可访问方法,它可以防止恶意实现。与可访问字段类似,显著的静态值。如果您要编写可能成为库的一部分的代码,则需要非常清楚这一点。

    例如,对于典型的Web或桌面应用程序代码来说,它远不那么重要。然而,它在字段上的缺失使得代码更难阅读,并表明程序员很困惑。这样的代码不太可能是安全的,因为它写得不好。

        5
  •  4
  •   Yishai    14 年前

    一般来说,私人和其他类似的结构应该更多地被视为一般的偏好声明,而不是严格执行安全性。

    但是,如果您控制JVM进程正在运行(例如,您在JVM上运行其他代码提供的代码),那么最终的和私有的确实提供了安全性——再加上Java的SuffigMealMeor。通过反射可以避免这些限制。

    你不能做的是把代码发送到其他人的JVM上运行,并认为你以这种方式隐藏了任何东西。

    编辑:Tom提醒我,通过正确使用最终字段,还可以部分防止序列化攻击(故意提供序列化数据的错误二进制流)。有效的Java有更多这样的例子。

        6
  •  3
  •   Kevin    14 年前

    它不会使您的代码更安全,它更多的是为了线程安全。如果变量被标记为final,则在创建对象时必须为其赋值。对象创建后,不能使该变量引用另一个值。

    此行为允许您推断对象的状态,并在多个线程同时访问对象时进行某些假设。

        7
  •  2
  •   danben    14 年前

    我想有人这么说是什么意思 final 使您的代码更安全的原因是它阻止未来的开发人员来修改不应该修改的值,或者从设计为不可扩展的类继承(并在过程中导致不可预知的结果)。它与身份验证没有任何关系(直接)。

        8
  •  2
  •   C Johnson    14 年前

    我很确定final是一个设计构造,其方式与访问修饰符在类声明中的方式大致相同——它是一种表达和执行设计的方式。

        9
  •  1
  •   Sarfraz    14 年前

    它更多的是“改变”东西,而不是“保护”。最后的关键字只会使更改/修改/扩展任何方法的能力消失。

        10
  •  1
  •   MindStalker    14 年前

    Final还改进了性能/内存管理。

        11
  •  1
  •   Steven Schlansker    14 年前

    “final”关键字确实有一些安全隐患。假设您正在设计一个安全的系统,该系统有一个服务,给定一个字符串,在且仅当该字符串有效时才执行某些操作。你可以写:

    public void doSomethingUseful(String argument) {
        checkValidity(argument);
        /* prepare to do something useful... preparation takes a bit of time! */
        reallyDoTheUsefulTask(argument);
    }
    

    如果字符串不是最终的,一些聪明的攻击者可以对字符串进行子类化。它们的字符串并不像stock-string类那样是不可变的-事实上,它们可以生成另一个线程,并尝试通过在checkvalidity之后但实际使用参数之前更改参数来攻击您的方法。然后你的“有用的任务”突然做了一些完全错误的事情,可能会危及安全。他们刚刚绕过了你的支票!但是,因为java.lang.string是最终的,所以您可以很好地保证,当您请求一个字符串参数时,它实际上是标准的不可变字符串。这是一个相当大的问题——有一类内核模式攻击是基于对系统调用的参数处理不当。

    所以是的,final可以有一些安全考虑。

        12
  •  1
  •   Katie    9 年前

    final关键字通常用于保持不变。对类或方法使用final是为了防止方法之间的链接被破坏。例如,假设X类的某个方法的实现假定M方法将以某种方式工作。将x或m声明为final将防止派生类重新定义m,从而导致x的行为不正确。它保护对象和方法不被操纵。但是对于加密来说,使用final关键字并不是解决方案。