我已经使用JAAS构建了一个客户端/服务器应用程序。登录似乎正常,因为登录成功。在尝试向AccessController
开始投射AccessControlException
的特定方法授予权限时。
java.security.AccessControlException: access denied ("myPackage.CustomPermission" "someMethod")
许可级别:
public class CustomPermission extends BasicPermission {
public CustomPermission(String name) {
super(name);
}
public CustomPermission(String name, String method) {
super(name, method);
}
}
我也有一个自定义的Principal-class:
public class CustomPrincipal implements Principal {
private String name;
public CustomPrincipal(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
登录时,用户提供用户名和密码。在数据库中,用户名和密码具有"用户级别"与他们相关联。这些用户级别用作主体名称,添加到登录时创建的Subject
。我在处理commit
中的LoginModule
- 方法时添加它:
public boolean commit() throws LoginException {
if(status == ConfigValues.NOT || subject == null)
return false;
principal = new CustomPrincipal(userlvl);
if(subject.getPrincipals().add(principal)) {
username = null;
password = null;
status = ConfigValues.COMMIT;
return true;
}
return false;
}
为此,我实例化登录程序:
LoginContext lc = new LoginContext("MyLoginModule", new RemoteCallbackHandler(username, password));
lc.login();
new ServerImpl(lc.getSubject());
Subject
然后用于"代理"用于检查权限的服务器实现,如(user = lc.getSubject
):
public String someMethod() throws RemoteException, PrivilegedActionException {
return Subject.doAs(user, new PrivilegedExceptionAction<String>() {
@Override
public String run() throws PrivilegedActionException, RemoteException, ServerNotActiveException {
AccessController.checkPermission(new CustomPermission("someMethod"));
return realServerImplObj.someMethod();
}
});
}
.policy文件:
grant codeBase "file:./bin/-" Principal myPackage.CustomPrincipal "user" {
permission myPackage.CustomPermission "someMethod";
};
&#34;用户&#34;当然是您可以登录的用户级别之一。
我试图添加一些额外的拨款,例如:
grant codeBase "file:./bin/-" {
permission javax.security.auth.AuthPermission "createLoginContext.MyLoginModule";
permission javax.security.auth.AuthPermission "doAs";
};
我也有LoginModule的配置:
MyLoginModule {
myPackage.MyLoginModule required debug=true;
};
我在之前设置属性,当然:编辑:文件位于项目的根目录
System.setProperty("java.security.auth.login.config", "file:./MyConfig.config");
System.setProperty("java.security.policy", "file:./MyPolicy.policy");
服务器使用-Djava.security.manager
参数运行。客户端不使用任何参数,也不使用任何配置或策略文件。
我试图删除codeBase以查看我的路径是否错误。如果我添加permissions java.util.AllPermissions
,那么一切都很好(但......当然它并不好,因为这绝对不是预期的)。这里有什么问题?我想它是Principal-,Permission,.policiy-和LoginModule-实现的组合。
修改
这是在&#34;代理&#34;中调用AccessController.checkPermissions(...)
的时候。抛出异常的服务器实现。
编辑2 我尝试过以下代码编辑:
return AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
@Override
public String run() throws PrivilegedActionException, RemoteException, ServerNotActiveException {
//AccessController.checkPermission(new CustomPermission("someMethod"));
return realServerImplObj.someMethod();
}
});
请注意,我已将Subject.doAs(user, new Privile....
更改为AccessController.doPrivileged(new Privilege
。
参数中不再解析user
,我们使用静态方法AccessController.doPrivileged
,而不是Subject.doAs
。
另一个说明:
//AccessController.checkPermission(new CustomPer...
已被评论过。
但是现在每个人都可以调用任何方法,因为我们实际上从不检查权限。 就好像AccessController永远不会知道.policy文件中授予的权限。
编辑3 这个问题似乎是校长实施的一个问题。
为了澄清,这些是已经进行的编辑:
@Override
public String someMethod() throws PrivilegedActionException {
return Subject.doAsPrivileged(user, new PrivilegedExceptionAction<String>() {
@Override
public String run() throws PrivilegedActionException, RemoteException, ServerNotActiveException {
AccessController.checkPermission(new CustomPermission("someMethod"));
return realServerImplObj.someMethod();
}
}, null);
}
差异是return Subject.doAsPrivileged(user, ... , null);
。注意最后的空值。
在CustomPrincipal
- 类,#equals(Object)
和#hashCode()
中实施了两种方法。有关这两种方法的一般用途示例,请参阅here,以及一般的Principal
示例实现。
还添加了(即使它似乎没有运行,实际上)以下.policy文件
grant codeBase "file:./bin/-" {
permission javax.security.auth.AuthPermission "createLoginContext.MyLoginModule";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "doAsPrivileged";
};
permission javax.security.auth.AuthPermission "doAsPrivileged";
是新添加的条目。
答案 0 :(得分:1)
Subject#doAs
vs Subject#doAsPrivileged
AccessController
使用的默认授权算法基于Permission
交集:如果AccessControlContext
的全部 ProtectionDomain
s,可能 combined Subject
Principal
s,具有静态和/或Policy
实际上,正在检查Permission
,评估成功;否则就失败了。
Subject#doAs
在您的情况下不起作用,因为Permission
grant
ProtectionDomain
与您Principal
的组合AccessController#checkPermission(customPermission)
,但不是域名本身。具体而言,在AccessControlContext
调用时,有效Permission
包含以下相关(至于Frame # | ProtectionDomain | Permissions
--------+---------------------------+---------------------------------------------
2 | "file:./bin/" | { CustomPermission("someMethod"),
| + CustomPrincipal("user") | permissions statically assigned by default
| | by the ClassLoader }
--------+---------------------------+---------------------------------------------
1 | "file:./bin/" | { AuthPermission(
| | "createLoginContext.MyLoginModule"),
| | AuthPermission("doAs"), default as above }
--------+---------------------------+---------------------------------------------
评估)框架:
CustomPermission
这些框架权限的交集当然不包括所需的Subject#doAsPrivileged
。
null AccessControlContext
时, doAsPrivileged
可以解决问题,因为它会将有效上下文的堆栈“修剪”到其最顶层的帧,即{ {1}}被调用。实际发生的情况是null
{em>} 上传AccessController
上下文,就像它是一个上下文,其权限评估产生{{ 1}};换句话说:
AllPermission
⋂权限 frame 2 = {AllPermission
,默认值},
这是(除了看似无关的静态分配CustomPermission("someMethod")
s的最小集合)所需的结果。
当然,如果不希望出现这种潜在的任意权限升级,则自定义上下文,其封装域的权限表示您愿意的最大权限集授权(例如某些Permnission
)可以传递给Subject
而不是doAsPrivileged
。
null
实施被迫覆盖Principal
和equals
?以下堆栈跟踪代码段说明了原因:
hashCode
进一步阅读: