我可以在Java中找到调用方法的对象吗?我有一个团体和人的社交网络。如果一个人想要离开一个团体,只有那个人可以从团体中移除,没有其他人可以移除那个人,不管怎样,调用该方法的人必须证明它的身份。
我可以在Java中找到调用方法的对象吗?我有一个团体和人的社交网络。如果一个人想要离开一个团体,只有那个人可以从团体中移除,没有其他人可以移除那个人,不管怎样,调用该方法的人必须证明它的身份。
检查方法的调用者是来自没有经验的程序员的相当普遍的请求。我很惊讶它在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<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);
}
}
(Objects.requireNonNull
遗漏了“简洁”。)
你可以这样做 反射 通过分析堆栈跟踪(如此问题中所述: 如何使用堆栈跟踪或反射找到方法的调用者?)。
但是,在大多数情况下,这将是滥用反思。您应该强烈考虑让您的方法采用额外的参数调用 caller
(调用者应该填写 this
)。
Oli解决方案的风险在于恶意代码可以调用'remove'方法并指定不同的调用方对象。
如果您使用的是安全框架(如Spring Security),则可以请求当前主体并仅允许从该组中删除该用户,或者如果该用户是管理员,则允许从该组中删除任何用户。