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

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

检查方法的调用者是来自没有经验的程序员的相当普遍的请求。 我很惊讶它在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()); } } 

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

 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)); } } 

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

 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 members = new IdentityHashSet<>(); // No Object.equals. public void registerPerson(Person person) { members.add(person); } public void deregisterPerson(Person person) { members.remove(person); } public Set members() { // This will be more concise in Java SE 8. Set publics = new HashSet<>(); for (Member member : members) { publics.add(member.publicPerson()); } return unmodifiableSet(publics); } } 

Objects.requireNonNull因“简洁”而被遗漏。)

您可以通过分析堆栈跟踪来进行reflection (如本问题中所述: 如何使用堆栈跟踪或reflection找到方法的调用方? )。

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

Oli解决方案的风险在于恶意代码可以调用’remove’方法并指定不同的调用方对象。

如果您使用的是安全框架(如Spring Security),则可以请求当前主体并仅允许从该组中删除该用户,或者如果该用户是管理员,则允许从该组中删除任何用户。