【问题标题】:JASPIC Wildfly 9 validateRequest with sessionJASPIC Wildfly 9 validateRequest 与会话
【发布时间】:2016-02-20 20:33:00
【问题描述】:

基于这个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.SimpleSecurityManagerline 367 的wilfly 的源代码,由于line 405,其中credential 被选中,但似乎是null

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

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

【问题讨论】:

    标签: java session ejb wildfly jaspic


    【解决方案1】:

    这听起来对我来说也是一个错误,因为调用者身份(调用者/组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 回调属性,而是使用 @ 987654329@ 在每次validateRequest(...) 调用时注册调用者Principal 其组。如果适用于您的用例,您可能希望将该信息附加到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),它似乎按预期工作。显然我不能保证这种方法不会以其他意想不到的方式失败。


    也可以看看:

    【讨论】:

    • 我尝试了这种解决方法,但 tp = (TokenPrincipal) hs.getAttribute(callerSessionKey);never 返回与 null 不同的内容,在我的示例中,Wildfly 9.0.02 似乎从不使用相同的会话。
    • 愚蠢的问题,但只是为了确定——您实际上是在某处创建会话,对吗?由于我不确定是否可以选择使用 HTTP 会话(您可能希望保持完全无状态,HTTP 会话方式),所以上面的示例没有,并且只附加调用者及其角色(如果有)已经是一个活动会话。如果您确实在其他地方创建了会话并且 SAM 仍然无法检索信息,请告诉我,我将在明天重新测试。否则,在 SAM 中进行初始身份验证时,req.getSession(false) 将需要变为 req.getSession()
    • 它对我不起作用,因为在web.xml 中强制执行 ssl 加密,但不存在。谢谢!您的答案是我将使用的解决方法。
    • @knoe 和 Uux:这听起来确实是一个令人讨厌的错误。你们中有人尝试向 JBoss 报告吗?
    • @knoe 和 Uux;我终于找到了一些时间来了解这个问题的根源,并与 JBoss 报告了它。请参阅issues.jboss.org/browse/WFLY-6579 我使用修改后的 JBoss 内部类创建了一个临时补丁:github.com/omnifaces/omnisecurity-jaspic-undertow/blob/master/…
    猜你喜欢
    • 2016-02-18
    • 2016-10-28
    • 2023-03-19
    • 2015-08-10
    • 2016-01-28
    • 2017-12-18
    • 2014-11-03
    • 2013-02-27
    • 1970-01-01
    相关资源
    最近更新 更多