java - JASPIC Wildfly 9 validateRequest with session

标签 java session ejb wildfly jaspic

基于此Jaspic Example我为 ServerAuthModule 编写了以下 validateRequest 方法:

public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject,
        Subject serviceSubject) throws AuthException {

    boolean authenticated = false;
    final HttpServletRequest request = 
                      (HttpServletRequest) messageInfo.getRequestMessage();
    final String token = request.getParameter("token");
    TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal();

    Callback[] callbacks = new Callback[] {
            new CallerPrincipalCallback(clientSubject, (TokenPrincipal) null) };

    if (principal != null) {
        callbacks = new Callback[] { 
                new CallerPrincipalCallback(clientSubject, principal) };
        authenticated = true;
    } else {
        if (token != null && token.length() == Constants.tokenLength) {
            try {
                principal = fetchUser(token);
            } catch (final Exception e) {
                throw (AuthException) new AuthException().initCause(e);
            }
            callbacks = new Callback[]
                        { 
                             new CallerPrincipalCallback(clientSubject, principal),
                             new GroupPrincipalCallback(clientSubject,
                                                        new String[] { "aRole" })
                        };
            messageInfo.getMap().put("javax.servlet.http.registerSession", "TRUE");
            authenticated = true;
        }
    }

    if (authenticated) {
        try {
            handler.handle(callbacks);
        } catch (final Exception e) {
            throw (AuthException) new AuthException().initCause(e);
        }
        return SUCCESS;
    }

    return AuthStatus.SEND_FAILURE;
}

这按预期工作,对于带有 @RolesAllowed("aRole") 的 ejb 的第一次调用,但对于下一次调用,这根本不起作用。 Wildfly 拒绝它并显示此错误消息:

ERROR [org.jboss.as.ejb3.invocation] (default task-4) WFLYEJB0034: EJB Invocation 
    failed on component TestEJB for method public java.lang.String 
    com.jaspic.security.TestEJB.getPrincipalName():
    javax.ejb.EJBAccessException: WFLYSEC0027: Invalid User

如果我猜对了,错误发生在: org.jboss.as.security.service.SimpleSecurityManager line 367 wilfly 的源代码,由于 line 405 ,其中检查了 credential,但似乎是 null

这在 Wildfly 8/9/10CR 中似乎相同(其他版本未测试)。

我再次不确定,如果我做错了,或者这是否与 https://issues.jboss.org/browse/WFLY-4626 ?它到底是一个错误,还是预期的行为?

最佳答案

这对我来说也像是一个错误,因为调用者身份(调用者/组 Principals)似乎在随后的 Web 调用中保留,而不是 EJB 容器。我自己的 JASPIC 类(在 GlassFish 4.1 上正常运行)在 WildFly 9.0.2.Final 和 10.0.0.CR4 上与普通 Servlet 和 SLSB 一起使用时出于同样的原因失败,即使后者标记为 @ PermitAll.

由于我自己不熟悉 WildFly 安全内部机制,因此无法在这方面为您提供帮助。除非你能得到这个补丁,否则我目前能想到的唯一 SAM 级别的解决方法是使用javax.servlet.http.registerSession 回调属性这似乎触发了问题,而是让 CallbackHandler 在每个 validateRequest(... ) 调用。如果适用于您的用例,您可能希望将该信息附加到 HttpSession 以稍微加快该过程;否则从头开始重复。所以,例如:

public class Sam implements ServerAuthModule {

    // ...

    @Override
    public AuthStatus validateRequest(MessageInfo mi, Subject client, Subject service) throws AuthException {
        boolean authenticated = false;
        boolean attachAuthnInfoToSession = false;
        final String callerSessionKey = "authn.caller";
        final String groupsSessionKey = "authn.groups";
        final HttpServletRequest req = (HttpServletRequest) mi.getRequestMessage();
        TokenPrincipal tp = null;
        String[] groups = null;
        String token = null;
        HttpSession hs = req.getSession(false);
        if (hs != null) {
            tp = (TokenPrincipal) hs.getAttribute(callerSessionKey);
            groups = (String[]) hs.getAttribute(groupsSessionKey);
        }
        Callback[] callbacks = null;
        if (tp != null) {
            callbacks = new Callback[] { new CallerPrincipalCallback(client, tp), new GroupPrincipalCallback(client, groups) };
            authenticated = true;
        }
        else if (isValid(token = req.getParameter("token"))) {
            tp = newTokenPrincipal(token);
            groups = fetchGroups(tp);
            callbacks = new Callback[] { new CallerPrincipalCallback(client, tp), new GroupPrincipalCallback(client, groups) };
            authenticated = true;
            attachAuthnInfoToSession = true;
        }
        if (authenticated) {
            try {
                handler.handle(callbacks);
                if (attachAuthnInfoToSession && ((hs = req.getSession(false)) != null)) {
                    hs.setAttribute(callerSessionKey, tp);
                    hs.setAttribute(groupsSessionKey, groups);
                }
            }
            catch (IOException | UnsupportedCallbackException e) {
                throw (AuthException) new AuthException().initCause(e);
            }
            return AuthStatus.SUCCESS;
        }
        return AuthStatus.SEND_FAILURE;
    }

    // ...

    @Override
    public void cleanSubject(MessageInfo mi, Subject subject) throws AuthException {
        // ...
        // just to be safe
        HttpSession hs = ((HttpServletRequest) mi.getRequestMessage()).getSession(false);
        if (hs != null) {
            hs.invalidate();
        }
    }

    private boolean isValid(String token) {
        // whatever
        return ((token != null) && (token.length() == 10));
    }

    private TokenPrincipal newTokenPrincipal(String token) {
        // whatever
        return new TokenPrincipal(token);
    }

    private String[] fetchGroups(TokenPrincipal tp) {
        // whatever
        return new String[] { "aRole" };
    }

}

我在上述 WildFly 版本上以上述方式测试了上述内容(即使用单个 Servlet 引用标记为 @DeclareRoles/方法级 @RolesAllowed 的单个 SLSB ) 并且它似乎按预期工作。显然我不能保证这种方法不会以其他意想不到的方式失败。


另见:

关于java - JASPIC Wildfly 9 validateRequest with session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33791367/

相关文章:

java - 使用 JSmooth 将 Jar 转换为 exe - 找不到主类

java - 嵌套控制结构,平均脚本

java - 我怎样才能让这个程序也打印列表中的第一个条目?

php - 我应该调用一个包含 SESSION 值的变量而不是在 PHP 中调用实际 session 吗?

c# - Session_Start 在 Chrome 中被调用得太频繁

c# - 当负载均衡器不是 "sticky"时,如何在 MVC 的 Session 中保存数据?

java - EJB调用WebLogic和OpenEJB中的EJB

maven - 如何使用 maven 发布本地和远程 ejb api

java - 如何将参数传递给 java 中的方法,如 python 中的 f(*args)?

jakarta-ee - java :comp/env is not found when using openejb in embedded mode