JBoss EAP 6.3 / AS 7 具有不安全页面的集群 SSO
JBoss EAP 6.3 / AS 7 Clustered SSO with unsecured pages
我正在尝试让集群 SSO 在 JBoss EAP 6.3.2(相当于 JBoss AS 7.4.x)中工作,我的会话复制工作正常,但是 SSO (用户主体复制)并非在所有情况下都有效。
当我使用在具有适当角色的 <auth-constraint>
的 <security-contraint>
中保护的 servlet 时,它工作正常。
但是对于未受保护的 servlet,SSO 在我第一次访问受保护页面之前不起作用,这似乎启动了 SSO,然后 infinispan 在集群中找到了用户主体。
这是个问题,因为无论您是否登录,我的许多页面的行为都不同。
我有一个狡猾的解决方法,我在 valve 中调用 reauthenticateFromSSO
,但是直到后续请求才起作用(我想我在链中来不及了)。我可能可以做一个 servlet FORWARD 来解决这个问题,但它看起来很狡猾。
在 standalone.xml 中,我尝试在 <sso cache-container="web" cache-name="sso" reauthenticate="true"/>
行中设置 reauthenticate=true
,但这似乎导致每次我在集群中的不同服务器上结束时注销。
JBoss 中是否有一些神奇的设置可以让它在不需要身份验证的页面上重新验证 SSO?
感谢@FedericoSierra 的一些澄清,在 super.invoke(request, response);
之前调用 super.reauthenticateFromSSO
解决了我的问题。我附上了下面的代码。
理论上检查 request.getPrincipal() == null && ssoID != null
可能也足够了。
ClusteredSSOFailoverValve.java
package com.mycompany.valve;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jboss.as.web.security.ExtendedFormAuthenticator;
import com.yourcompany.framework.Loggers;
/**
* Enables Clustered Single Sign On session failover for servlets that don't have any security defined in the web.xml
*/
public class ClusteredSSOFailoverValve extends ExtendedFormAuthenticator {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
if (request.getSession(false) != null && request.getPrincipal() == null) {
// Try to find the session from Infinispan
// The REQ_SSOID_NOTE is set by org.jboss.as.web.sso.ClusteredSingleSignOn.invoke(Request, Response)
Object ssoID = request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoID != null && ssoID instanceof String) {
if (Loggers.securityLogger.isDebugEnabled()) {
Loggers.securityLogger
.debug("Found SSO Session ID ["
+ ssoID
+ "] with a null principal, so will attempt a re-authenticate from SSO to try and retrieve the user principal from the cluster");
}
super.reauthenticateFromSSO((String) ssoID, request);
if (Loggers.securityLogger.isDebugEnabled()) {
Loggers.securityLogger.debug("After re-authenticate from SSO with ssoID [" + ssoID + "], principal is now ["
+ request.getPrincipal() + "]");
}
}
}
super.invoke(request, response);
}
}
WEB-INF/jboss-web.xml
<?xml version='1.0' encoding='UTF-8' ?>
<jboss-web>
<security-domain>sso</security-domain>
<valve>
<class-name>com.mycompany.valve.ClusteredSSOFailoverValve</class-name>
</valve>
</jboss-web>
我正在尝试让集群 SSO 在 JBoss EAP 6.3.2(相当于 JBoss AS 7.4.x)中工作,我的会话复制工作正常,但是 SSO (用户主体复制)并非在所有情况下都有效。
当我使用在具有适当角色的 <auth-constraint>
的 <security-contraint>
中保护的 servlet 时,它工作正常。
但是对于未受保护的 servlet,SSO 在我第一次访问受保护页面之前不起作用,这似乎启动了 SSO,然后 infinispan 在集群中找到了用户主体。
这是个问题,因为无论您是否登录,我的许多页面的行为都不同。
我有一个狡猾的解决方法,我在 valve 中调用 reauthenticateFromSSO
,但是直到后续请求才起作用(我想我在链中来不及了)。我可能可以做一个 servlet FORWARD 来解决这个问题,但它看起来很狡猾。
在 standalone.xml 中,我尝试在 <sso cache-container="web" cache-name="sso" reauthenticate="true"/>
行中设置 reauthenticate=true
,但这似乎导致每次我在集群中的不同服务器上结束时注销。
JBoss 中是否有一些神奇的设置可以让它在不需要身份验证的页面上重新验证 SSO?
感谢@FedericoSierra 的一些澄清,在 super.invoke(request, response);
之前调用 super.reauthenticateFromSSO
解决了我的问题。我附上了下面的代码。
理论上检查 request.getPrincipal() == null && ssoID != null
可能也足够了。
ClusteredSSOFailoverValve.java
package com.mycompany.valve;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jboss.as.web.security.ExtendedFormAuthenticator;
import com.yourcompany.framework.Loggers;
/**
* Enables Clustered Single Sign On session failover for servlets that don't have any security defined in the web.xml
*/
public class ClusteredSSOFailoverValve extends ExtendedFormAuthenticator {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
if (request.getSession(false) != null && request.getPrincipal() == null) {
// Try to find the session from Infinispan
// The REQ_SSOID_NOTE is set by org.jboss.as.web.sso.ClusteredSingleSignOn.invoke(Request, Response)
Object ssoID = request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoID != null && ssoID instanceof String) {
if (Loggers.securityLogger.isDebugEnabled()) {
Loggers.securityLogger
.debug("Found SSO Session ID ["
+ ssoID
+ "] with a null principal, so will attempt a re-authenticate from SSO to try and retrieve the user principal from the cluster");
}
super.reauthenticateFromSSO((String) ssoID, request);
if (Loggers.securityLogger.isDebugEnabled()) {
Loggers.securityLogger.debug("After re-authenticate from SSO with ssoID [" + ssoID + "], principal is now ["
+ request.getPrincipal() + "]");
}
}
}
super.invoke(request, response);
}
}
WEB-INF/jboss-web.xml
<?xml version='1.0' encoding='UTF-8' ?>
<jboss-web>
<security-domain>sso</security-domain>
<valve>
<class-name>com.mycompany.valve.ClusteredSSOFailoverValve</class-name>
</valve>
</jboss-web>