JASPIC Wildfly 9使用会话验证请求

时间:2015-11-18 22:06:49

标签: java session ejb wildfly jaspic

根据此Jaspic Example,我为validateRequest编写了以下ServerAuthModule方法:

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

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

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

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

1 个答案:

答案 0 :(得分:7)

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

由于我自己不熟悉WildFly安全内部人员,我无法在这方面为您提供帮助。除非您可以修补此问题,否则我现在可以想到的唯一SAM级解决方法是使用看似触发问题的@PermitAll回调属性,而是javax.servlet.http.registerSession在每次CallbackHandler次调用时都会向调用者Principal 注册其组。如果适用于您的使用案例,您可能希望将该信息附加到validateRequest(...),以便加快处理速度;否则从头开始重复。所以,例如:

HttpSession

我在前面提到的WildFly版本上以上述方式测试了上述内容(即使用单个Servlet引用标记为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" }; } } /方法级@DeclareRoles的单个SLSB),它似乎按预期工作。显然,我不能保证这种方法不会以其他意想不到的方式失败。

<小时/> 另见: