使用JAAS

时间:2016-11-22 16:57:20

标签: java access-control jaas accesscontrolexception

我已经使用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";是新添加的条目。

1 个答案:

答案 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实施被迫覆盖Principalequals

以下堆栈跟踪代码段说明了原因:

hashCode

进一步阅读: