Jsf 使用CustomFormAuth和o:form登录时未正确转发
我试图在我的web项目上实现雅加达安全性,为此我遵循了Bauke Scholtz和Arjan Tijms令人惊叹的“JavaEE8中JSF的权威指南”,但似乎我遇到了麻烦 当我在地址栏中键入受限url时,转发会正常进行,我看到登录页面,但在提交表单后,页面不会重定向,登录页面似乎会重新加载(字段为空,但地址栏中的url仍然是受限页面中的url) 在日志的帮助下,我知道Jsf 使用CustomFormAuth和o:form登录时未正确转发,jsf,jakarta-ee,omnifaces,java-ee-8,Jsf,Jakarta Ee,Omnifaces,Java Ee 8,我试图在我的web项目上实现雅加达安全性,为此我遵循了Bauke Scholtz和Arjan Tijms令人惊叹的“JavaEE8中JSF的权威指南”,但似乎我遇到了麻烦 当我在地址栏中键入受限url时,转发会正常进行,我看到登录页面,但在提交表单后,页面不会重定向,登录页面似乎会重新加载(字段为空,但地址栏中的url仍然是受限页面中的url) 在日志的帮助下,我知道AuthenticationStatus返回为SUCCESS,但即使如此,如果我手动将地址栏更改为另一个受限url,它也会被转发到
AuthenticationStatus
返回为SUCCESS
,但即使如此,如果我手动将地址栏更改为另一个受限url,它也会被转发到登录页面
如果我在地址栏中键入/登录并提交,验证和重定向将正常进行
如果我使useForwardToLogin=false
正常工作,但是getForwardURL
总是返回null,并且我无法将用户重定向到他们想要访问的页面
谢谢你的帮助
ApplicationConfig.java
@CustomFormAuthenticationMechanismDefinition(
loginToContinue = @LoginToContinue(
loginPage = "/login",
errorPage = ""
)
)
@FacesConfig
@ApplicationScoped
public class ApplicationConfig {
}
login.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui"
template="/WEB-INF/templates/login.xhtml">
<ui:define name="content">
<c:choose>
<c:when test="#{not empty request.userPrincipal}">
<div>Already logged</div>
</c:when>
<c:otherwise>
<o:form>
<p:inputText id="login" value="#{loginBacking.userName}" required="true"/>
<p:password id="pwd" value="#{loginBacking.password}" required="true"/>
<p:inputNumber id="otp" value="#{loginBacking.otp}" />
<o:messages id="messages" var="message">
<div class="#{fn:toLowerCase(message.severity)}">#{message.summary}</div>
</o:messages>
<p:commandButton value="Submit" action="#{loginBacking.login}" update="@form"/>
</o:form>
</c:otherwise>
</c:choose>
</ui:define>
</ui:composition>
FIY,如你所见,我正在使用Omnifaces、Primefaces和Lombok。根据Kukeltje的建议,我制作了一个你可以在这里找到的最简单的工作示例。 它是由Bauke Scholtz和Arjan Tijms=>撰写的《JavaEE8中JSF的最终指南》一书中repo安全部分的一个修改分支 它工作得非常好,所以我决定添加omnifaces和primefaces,并意识到:
p:commandButton
,那么应该向其添加ajax=false
属性o:form
,则应向其添加useRequestURI=“false”
属性。这是有意义的,因为my fork使用forward来访问登录页面,所以URL和URI是您想要访问的任何页面的URL和URI,并且当o:form上的useRequestURI
设置为true
(默认值)时,它会提交表单,因此不会提交到登录页面非常感谢Kukeltje为我指明了正确的方向。我有似曾相识的经历…@Kukeltje我也是:。不管怎样,我找到了一个解决办法。我想我没有找到合适的工作来寻找类似的问题,对不起@Kukeltje我看到了这篇文章,但是在commandButton中添加ajax=false并没有改变任何事情@Marcos,我也应该实现OTP,所以我不能使用
@FormAuthenticationMechanismDefinition
SylvainAutran:我也找不到最近类似的帖子。。。奇怪的因此,感谢@Marcos将其链接。。我们会看看是否能找到原因和解决办法。你能做一个没有模板,没有jstl,没有lombok,没有简单的jsf组件,没有omnifaces等吗?是的,我会尝试这样做。你使用的是什么应用服务器?Payara 5,版本201和2020.2我在Wildfly 20中克隆并执行了你的示例。当执行方法Login#continueAuthentication
时,我被重定向到500.xhtml页面,服务器JSF实现中出现NullPointerException
错误:UT005023:异常处理请求到/jakartasecurity/login.xhtml:javax.servlet.ServletException:java.lang.NullPointerException
javax.faces。api@3.0.0.SP03//javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:725)
因此,该漏洞似乎在Wildfly中,而不是在我的应用程序或您的示例中。@Marcos:关于您的问题的评论应该在您的问题中!
@Named
@RequestScoped
public class LoginBacking {
@Inject private SecurityContext securityContext;
@Getter @Setter private String userName;
@Getter @Setter private String password;
@Getter @Setter private Integer otp;
public void login() {
switch (continueAuthentication()) {
case SEND_CONTINUE:
Faces.responseComplete();
break;
case SEND_FAILURE:
Messages.addGlobalFatal("Login failed.");
break;
case SUCCESS:
redirect();
break;
}
}
private AuthenticationStatus continueAuthentication() {
return this.securityContext.authenticate(
Faces.getRequest(),
Faces.getResponse(),
AuthenticationParameters.withParams()
.newAuthentication(getForwardURL() == null)
.credential(new CustomCredential(userName, password, otp))
);
}
private void redirect() {
CustomUser user = securityContext.getPrincipalsByType(CustomPrincipal.class).stream()
.map(CustomPrincipal::getCustomUser)
.findAny()
.orElse(null);
if (user == null) Messages.addGlobalFatal("Something went wrong.");
String forwardURL = getForwardURL();
if (forwardURL != null) {
Faces.redirect(forwardURL);
return;
}
Faces.redirect(Faces.getRequestContextPath() + "/restricted/index");
}
public void logout() throws ServletException {
Faces.logout();
Faces.invalidateSession();
Faces.redirect("login");
}
public String getForwardURL() {
String requestURI = Faces.getRequestAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
String queryString = Faces.getRequestAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
if (requestURI == null) return null;
return (queryString == null) ? requestURI : (requestURI + "?" + queryString);
}
}