JASPIC Wildfly 9 validateRequest with session
JASPIC Wildfly 9 validateRequest with session
基于此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 of wilfly's source code, due to line 405,其中勾选了credential
,但好像是null
。
这在 Wildfly 8/9/10CR 中似乎相同(其他版本未测试)。
我再次不确定,如果我做错了,或者这是否与
https://issues.jboss.org/browse/WFLY-4626 ?它到底是一个错误,还是预期的行为?
这对我来说也像是一个错误,因为调用者身份(调用者/组 Principal
s)似乎在随后的 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(...)
调用时注册调用者 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)并且它似乎可以工作正如预期的那样。显然我不能保证这种方法不会以其他意想不到的方式失败。
另见:
基于此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 of wilfly's source code, due to line 405,其中勾选了credential
,但好像是null
。
这在 Wildfly 8/9/10CR 中似乎相同(其他版本未测试)。
我再次不确定,如果我做错了,或者这是否与 https://issues.jboss.org/browse/WFLY-4626 ?它到底是一个错误,还是预期的行为?
这对我来说也像是一个错误,因为调用者身份(调用者/组 Principal
s)似乎在随后的 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(...)
调用时注册调用者 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)并且它似乎可以工作正如预期的那样。显然我不能保证这种方法不会以其他意想不到的方式失败。
另见: