我需要记住Http Request
的原始URL,然后将此请求重定向到web表单以进行用户身份验证。如果身份验证成功,则必须将用户重定向到上面刚刚记住的original URL
。我使用的是标准web.xml
JBoss 7.1.1 Final
和JBoss登录模块org.jboss.security.auth.spi.DatabaseServerLoginModule
:
我提到了以下链接,但这些链接并没有完全回答我的问题:
-
中安全约束相对于筛选器的优先级Servlet
-
Jaspic ServerAuthModule委托给JAAS Krb5LoginModule
-
用JASPIC 在Java EE中实现容器身份验证
- 《Oracle GlassFish Server 3.0.1应用程序开发指南》
然而,在实现我的解决方案后,我的自定义ServerAuthModule根本没有被调用。更糟糕的是,我没有从服务器上得到任何HttpResponse。有东西坏了,请帮帮我!
我的web.xml
:
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources in /pages/*</web-resource-name>
<description>All resources in /pages/*</description>
<url-pattern>/pages/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>general</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<display-name>Restrict direct access to the /resources folder.</display-name>
<web-resource-collection>
<web-resource-name>The /resources folder.</web-resource-name>
<url-pattern>/resources/*</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/loginFailed.jsf</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>general</role-name>
</security-role>
我的jboss-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>jBossJaasMysqlRealm</security-domain>
<valve>
<class-name>org.jboss.as.web.security.jaspi.WebJASPIAuthenticator</class-name>
</valve>
</jboss-web>
我的standalone.xml
:
<security-domain name="jBossJaasMysqlRealm" cache-type="default">
<authentication-jaspi>
<login-module-stack name="lm-stack">
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
<module-option name="dsJndiName" value="java:/MySqlDS_IamOK"/>
<module-option name="principalsQuery" value="select password from user where username=?"/>
<module-option name="rolesQuery" value="select role, 'Roles' from user_role where username=?"/>
</login-module>
</login-module-stack>
<auth-module code="at.alex.ok.web.utils.RequestMarkerServerAuthModule" login-module-stack-ref="lm-stack"/>
</authentication-jaspi>
</security-domain>
我的自定义WebServerAuthModule
:
import org.jboss.as.web.security.jaspi.modules.WebServerAuthModule;
public class RequestMarkerServerAuthModule extends WebServerAuthModule {
public static final String ORIGINAL_URL = "originalURL";
protected static final Class[] supportedMessageTypes = new Class[] {
HttpServletRequest.class, HttpServletResponse.class };
public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy,
CallbackHandler cBH, Map opts) throws AuthException {
System.out.println( this.getClass().getName() + ".initialize() called");
}
public Class[] getSupportedMessageTypes() {
return supportedMessageTypes;
}
public AuthStatus validateRequest(MessageInfo msgInfo, Subject client,
Subject server) throws AuthException {
try {
System.out.println( this.getClass().getName() + ".validateRequest() called");
processAuthorizationToken(msgInfo, client);
return AuthStatus.SUCCESS;
} catch (Exception e) {
AuthException ae = new AuthException();
ae.initCause(e);
throw ae;
}
}
private void processAuthorizationToken(MessageInfo msgInfo, Subject s)
throws AuthException {
HttpServletRequest request = (HttpServletRequest) msgInfo
.getRequestMessage();
String originalURL = request.getRequestURL().toString();
request.getSession().setAttribute(ORIGINAL_URL, originalURL);
}
public AuthStatus secureResponse(MessageInfo msgInfo, Subject service)
throws AuthException {
System.out.println( this.getClass().getName() + ".secureResponse() called");
return AuthStatus.SEND_SUCCESS;
}
public void cleanSubject(MessageInfo msgInfo, Subject subject)
throws AuthException {
System.out.println( this.getClass().getName() + ".cleanSubject() called");
}
}
这个问题提出得不正确,因为:对于成功登录后重定向到最初请求的URL,不需要为JBoss实现自定义ServerAuthModule。
接口javax.servlet.RequestDispatcher具有常量FORWARD_REQUEST_URI,它表示Http-REQUEST属性的名称,在该属性下,原始请求URI可用于转发请求的处理器。
使用JSF 2.2和View Scoped backingbean LoginBean,我的解决方案只是在backingbean的@PostConstruct方法中获得最初请求的URL,并将其存储在会话属性中,如下所示:
@ManagedBean(name="loginBean")
@ViewScoped
public class LoginBean {
private String originalURL;
@PostConstruct
private void init() {
ExternalContext extCtx = FacesContext.getCurrentInstance().getExternalContext();
String origURL = (String) extCtx.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
HttpServletRequest request = (HttpServletRequest) extCtx.getRequest();
HttpSession session = (HttpSession)extCtx.getSession(false);
if (session == null){
session = (HttpSession)extCtx.getSession(true);
}
if (origURL!=null && session.getAttribute(ORIGINAL_URL) == null){
String applicationName = request.getContextPath();
origURL = origURL.substring(applicationName.length(), origURL.length());
session.setAttribute(ORIGINAL_URL, origURL);
}
}
然后,在同一个backingbean的login()方法中,如果成功登录,则将用户重定向到最初请求的URL,如下所示:
public String login() {
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
try {
request.login(this.getLogin(), this.getPassword());
} catch (ServletException e) {
// handle bad username / password here
}
return this.originalURL + "?faces-redirect=true";
}