微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

跟进:Java中没有枚举的实例控件

这是 this question的后续行动.这个解决方案是否具有防水功能
public final class Thing implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final Thing[] instances = new Thing[2];
    private static int nextOrdinal = 0;

    public static final Thing instance0 = new Thing("whatever0");
    public static final Thing instance1 = new Thing("whatever1");

    private transient final String someState;

    public String someMethod() {return someState;}

    private final int ordinal;

    private Thing(String someState) {
        this.someState = someState;
        this.ordinal = nextOrdinaL++;
        instances[this.ordinal] = this;
    }

    private Object readResolve() throws ObjectStreamException {
        return instances[this.ordinal];
    }
}

解决方法

Is this solution watertight?

不.(虽然它可能是足够的,取决于代码的使用方式和位置.)

在第77项中:对于实例控制,首选枚举类型为readResolve(Effective Java,2nd ed),Bloch演示了攻击者如何拥有像您这样的类返回任何值.攻击依赖于手工制作的字节输入,并且能够在目标上运行代码(因此,如果在沙盒环境中使用,某些RMI情况等,则代码可能存在安全风险).我不知道这是否是唯一的攻击 – 它是唯一提到的攻击.解决方案是声明所有字段是瞬态的,但是您遇到了如何存储值的问题.

您可以使用序列化代理模式解决这些问题(书中的第78项 – 每个阅读它的Java程序员都推荐它的原因).

public final class Thing implements Serializable {
  private static final long serialVersionUID = 1L;
  private static final Thing[] INSTANCES = new Thing[2];
  private static int NEXT_ORDINAL = 0;

  public static final Thing INSTANCE0 = new Thing(
      "whatever0");
  public static final Thing INSTANCE1 = new Thing(
      "whatever1");

  private transient final String someState;

  public String someMethod() {
    return someState;
  }

  private final int ordinal;

  private Thing(String someState) {
    this.someState = someState;
    ordinal = NEXT_ORDINAL++;
    INSTANCES[ordinal] = this;
  }

  private Object writeReplace() {
    return new ThingProxy(this);
  }

  private void readobject(ObjectInputStream stream)
      throws InvalidobjectException {
    throw new InvalidobjectException("Proxy required");
  }

  private static class ThingProxy implements Serializable {
    private static final long serialVersionUID = 1L;
    private final int ordinal;

    private ThingProxy(Thing t) {
      ordinal = t.ordinal;
    }

    private Object readResolve()
        throws ObjectStreamException {
      return INSTANCES[ordinal];
    }

  }

}

虽然,与复制任何与互联网相关的安全性一样,但需要注意.我绝不是专家.

原文地址:https://www.jb51.cc/java/120733.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐