为用户分配角色

Assign roles to user

我试图将角色(管理员、用户)添加到正在工作的 Java EE 项目,而不是让所有用户都有权做所有事情。

我自己开始,修改 tables,编写自己的机制并计划用 @WebFilter 以编程方式控制它。

很快,我发现 Java EE 有一些看起来像是为此目的内置的机制。

我想用的是这个角色过滤器注解:

@RolesAllowed("ADMIN")
public void adminAllowedFunction(){
    //code
}

但是如何将角色分配给实际 user/session。另外,用户在这种情况下是什么意思?需要在 table 中记录以满足某些约定,或者我所做的只是将角色分配给实际会话?

我还阅读了一些有关将角色映射到 glassfish/payara 用户(领域)的内容。那是正确的方法吗?我没有找到明确解释的东西,只有 glassfish-web.xml 中的 <security-role-mapping>,但是如何在 java 代码中获取它?

我真的对 Java EE 机制感到困惑。我怀疑我没看懂是什么意思

我已经为所有角色尝试过 denny 这个功能:

@DenyAll
public String getUserName(){
    return (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("loggedUser");

}

但是我无法获取拒绝的条件

如果有任何有用的信息,我将不胜感激。另外,不要担心一堆代码示例。

通常您需要使用Java EE 身份验证机制。这种身份验证机制在请求开始时被调用,并将与调用者交互以获取凭据。如果这些凭据得到正确验证,它可以在当前请求中设置调用者姓名或调用者主体以及多个角色。

呼叫者姓名和角色的来源对于 Java EE 并不重要。您的代码可以即时创建它们、从内存存储中获取它们、从数据库中查询它们、从 LDAP 服务器中获取它们等等。

通常,但不一定,身份验证机制将验证凭据的任务委托给与如上所述的一种商店交互的专用组件。这称为 "identity store"(同样的事情还有大约 20 个其他术语,但 Java EE 对此进行了标准化)。

下面给出了身份存储的示例:

@ApplicationScoped
public class TestIdentityStore implements IdentityStore {

    public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {

        if (usernamePasswordCredential.compareTo("reza", "secret1")) {
            return new CredentialValidationResult("reza", new HashSet<>(asList("foo", "bar")));
        }

        return INVALID_RESULT;
    }

}

自定义身份验证机制如下所示:

@ApplicationScoped
public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {

    @Inject
    private IdentityStoreHandler identityStoreHandler;

    @Override
    public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {

        if (notNull(request.getParameter("name"), request.getParameter("password"))) {

            // Get the (caller) name and password from the request
            // NOTE: This is for the smallest possible example only. In practice
            // putting the password in a request query parameter is highly
            // insecure
            String name = request.getParameter("name");
            Password password = new Password(request.getParameter("password"));

            // Delegate the {credentials in -> identity data out} function to
            // the Identity Store
            CredentialValidationResult result = identityStoreHandler.validate(
                new UsernamePasswordCredential(name, password));

            if (result.getStatus() == VALID) {
                // Communicate the details of the authenticated user to the
                // container. In many cases the underlying handler will just store the details 
                // and the container will actually handle the login after we return from 
                // this method.
                return httpMessageContext.notifyContainerAboutLogin(
                    result.getCallerPrincipal(), result.getCallerGroups());
            } 

            return httpMessageContext.responseUnauthorized();
        } 

        return httpMessageContext.doNothing();
    }

}

请注意,以上仅用于DEMO目的,并非现实甚至安全的身份验证机制!

另请参阅:https://github.com/eclipse-ee4j/soteria/tree/master/test/app-mem/src/main/java/org/glassfish/soteria/test

通常您不会编写自己的身份验证机制甚至身份存储,但会重复使用 Java EE 提供的机制。例如:

@CustomFormAuthenticationMechanismDefinition(
    loginToContinue = @LoginToContinue(
        loginPage="/login.jsf",
        errorPage=""
    )
)
@ApplicationScoped
public class ApplicationInit {
}

用户的概念存在于查询或注入当前 caller/user 主体的能力中。例如使用:

@Inject
private Principal principal;

或使用例如Servlet API:

HttpServletRequest#getUserPrincipal();

这与 @RolesAllowed 和类似构造也检查的 "user"(经过身份验证的身份)相同。

组到角色的映射始终是可选的,并且默认组与角色相同。有些服务器甚至根本不支持组到角色的映射。