如何在Java中找到调用方法的对象

Joh*_*ith 12 java authentication

我可以在Java中找到调用方法的对象吗?我有一个团体和人的社交网络.如果一个人想要离开一个团体,只有那个人可以从团体中移除,没有其他人可以移除那个人,不管怎样,调用该方法的人必须证明它的身份.

Tom*_*ine 9

检查方法的调用者是来自没有经验的程序员的一个非常普遍的请求.我很惊讶它在SO上看起来并不常见.但这是一个非常糟糕的想法(只需查看Java 2(可能更糟糕的是)安全模型).

在很少的情况下,实施此限制很重要.正如Oli Charlesworth所说,只是不要这样做.但我们假设它很重要,但我们不打算进行堆栈检查.

让我们首先假设我们信任这个群体.一种有效但荒谬的方法是向该群体传递一个对象,该对象只代表该人可以创造的人.(注意Java语言访问限制是基于类的.不同的实例可以创建这样的替代,但代码必须在Person类中.)

public final class Group { // Can't have a malicious subclass.
    public void deregisterPerson(Person.Standin standin) {
        Person person = standin.person();
        ...
    }
}
public class Person { // May be subclassed.
    public final class Standin { // Could be one per Person.
        private Standin() { // Hide constructor from other outer classes.
        }
        public Person person() {
            return Person.this;
        }
    }
    private void groupDeregister(Group group) {
        group.deregisterPerson(new Standin());
    }
 }
Run Code Online (Sandbox Code Playgroud)

如果我们不信任该组,那么我们可以扩展该站点以引用该组.这可以防止恶意组将某个人从其他组中取消注册.

public class Group { // Can have malicious subclasses.
    public void deregisterPerson(Person.GroupDeregister deregister) {
        if (deregister.group() != this) { // Not equals...
            throw new IllegalArgumentException();
        }
        Person person = deregister.person();
        ...
    }
}
public class Person { // May be subclassed.
    public final class GroupDeregister {
        private final Group group;
        private GroupDeregister(Group group) { // Hidden.
            this.group = group;
        }
        public Person person() {
            return Person.this;
        }
        public Group group() {
            return group;
        }
    }
    private void groupDeregister(Group group) {
        group.deregisterPerson(new GroupDeregister(group));
    }
 }
Run Code Online (Sandbox Code Playgroud)

另一种方法是制作可以暴露给他人的"公开"版本的人.

public class Person { // "PrivatePerson"
    public PublicPerson publicPerson() {
         return new PublicPerson(this);
    }
    private void groupRegister(Group group) {
        group.registerPerson(this);
    }
    private void groupDeregister(Group group) {
        group.deregisterPerson(this);
    }
    ...
}
public class PublicPerson {
    private final Person person;
    public PublicPerson(Person person) {
        this.person = person;
    }
    @Override public final boolean equals(Object obj) {
        return obj instanceof Person && (Person)obj.person == person;
    }
    @Override public final int hashCode() {
        return person.hashCode();
    }
    ...methods, but no raw registration...
 }
 public class Group {
     private final Set<Person> members = new IdentityHashSet<>(); // No Object.equals.
     public void registerPerson(Person person) {
         members.add(person);
     }
     public void deregisterPerson(Person person) {
         members.remove(person);
     }
     public Set<PublicPerson> members() {
         // This will be more concise in Java SE 8.
         Set<PublicPerson> publics = new HashSet<>();
         for (Member member : members) {
             publics.add(member.publicPerson());
         }
         return unmodifiableSet(publics);
     }
}
Run Code Online (Sandbox Code Playgroud)

(Objects.requireNonNull留待"简洁".)


Oli*_*rth 5

您可以通过分析堆栈跟踪来使用反射来完成此操作(如本问题中所述: How do I find the caller of a method using stacktrace or Reflection?)。

然而,在大多数情况下,这将是对反射的滥用。您应该强烈考虑让您的方法采用一个名为 的额外参数caller(调用者应使用 填充该参数this)。

  • 该链接不相关:它找到调用者**类**,而不是**对象**。 (8认同)