简体   繁体   English

只允许从某些包构建对象

[英]Allowing object construction only from some packages

I work on a game-like system. 我在一个类似游戏的系统上工作。 Users can submit .class and .java files for customized behaviour. 用户可以提交.class和.java文件以进行自定义行为。 Some objects are delivered to the user via callback, but if the user can construct these object himself (with custom parameters), it would mean an advantage to him. 有些对象是通过回调传递给用户的,但是如果用户可以自己构造这些对象(使用自定义参数),则对他来说将是一个优势。 I will disallow reflection for the user and seal my packages. 我将禁止用户反射并密封我的包裹。 I can get this working if I abandon all package structure (and make the constructors package-private), but I would like not to do so. 如果我放弃所有包结构(并使构造函数包私有),则可以使此工作正常进行,但是我不想这样做。


Here is an example: 这是一个例子:

sscce.mycode.a.SomeClass.java : sscce.mycode.a.SomeClass.java

package sscce.mycode.a;

import sscce.mycode.b.RestrictedObject;
import sscce.usercode.SomeUserClass;

public class SomeClass {

    public static void main(String[] args) {
        SomeUserClass userClass=new SomeUserClass();

        // If I can create it from here, anyone can...
        RestrictedObject object=new RestrictedObject();

        userClass.someMethod(object);
    }

}

sscce.mycode.b.Interface.java : sscce.mycode.b.Interface.java

package sscce.mycode.b;

public interface Interface {

    public void someMethod(RestrictedObject restrictedObject);

}

sscce.mycode.b.RestrictedObject.java : sscce.mycode.b.RestrictedObject.java

package sscce.mycode.b;

public class RestrictedObject {

    public RestrictedObject() {}

}

sscce.usercode.SomeUserClass.java : sscce.usercode.SomeUserClass.java

package sscce.usercode;

import sscce.mycode.b.Interface;
import sscce.mycode.b.RestrictedObject;

public class SomeUserClass implements Interface {

    @Override
    public void someMethod(RestrictedObject restrictedObject) {
        // It receives an instance, but cannot create it.
        System.out.println("Got "+restrictedObject);
    }
}

Motivation : Having everything in one package sounds messy... 动机 :将所有内容打包在一起听起来很混乱……

Does anyone have ideas on how to accomplish this without flattening the packages? 有人对不弄平包装的情况有什么想法吗?
Thanks in advance for any solutions, ideas or comments, Till 在此先感谢您提供任何解决方案,想法或意见,直到

You could do it the following way, however you should carefully consider if you really want to use this approach as it is very slow and quite frankly, bad practice. 您可以按照以下方式进行操作,但是您应该认真考虑是否真的要使用这种方法,因为这种方法非常缓慢,坦率地说,这是不好的做法。 I'll put it up anyway as to how you can do it: 我把它作为反正你如何做到这一点:

public final class Secured {

  private static final Set<Class<?>> allowedCallers = new HashSet<>();

  static {
    allowedCallers.add(Allowed.class);
  }

  private static final class SecurityManagerExtension extends SecurityManager {

    private static final int OFFSET = 4;

    @Override
    protected Class<?>[] getClassContext() {
      return super.getClassContext();
    }

    private Class<?> getCaller() {
      try {
        return getClassContext()[OFFSET];
      } catch (ArrayIndexOutOfBoundsException e) {
        return null;
      }
    }
  }

  private Secured() {
    // protect against reflection attack
    Class<?> caller = new SecurityManagerExtension().getCaller();
    if (!this.getClass().equals(caller)) {
      throw new IllegalStateException();
    }
    System.out.println("Secured instance constructed!");
  }

  public static Secured createInstance() {
    // this gets the class name of the calling class
    Class<?> caller = new SecurityManagerExtension().getCaller();
    if (allowedCallers.contains(caller)) {
      System.out.println("Created instance by '" + caller + "'!");
      return new Secured();
    } else {
      System.out.println("No instance created because call was made by '" + caller + "'!");
      return null;
    }
  }
}

Note the final keyword on the class to prevent subclassing. 注意类上的final关键字以防止子类化。 If you need to subclass the class yourself, move the final keyword to the factory method. 如果您需要自己对类进行子类化,请将final关键字移至factory方法。 Also note that this is not protected against serialization attacks. 还要注意,这不能防止序列化攻击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM