我有一个JSF web应用程序,我需要提供如下所述的功能:
- 为了对某些内容发表评论,用户必须登录
- 如果他没有登录,那么"单击此处登录"会将他带到登录页面
- 成功登录必须将他重定向到他导航到登录页面的url
有什么办法可以做到这一点吗?
根据这个问题,您显然没有在web.xml
中使用带有领域和<security-constraint>
的容器管理身份验证。也就是说,它将完全透明地为您处理此问题。
我假设您已经自行生成了一个过滤器,当会话中没有登录用户时,该过滤器会将用户重定向到登录页面。在这种情况下,您还需要添加当前请求URL作为请求参数或会话属性。
下面是一个将其作为请求参数在过滤器中传递的示例:
if (user == null) {
String from = URLEncoder.encode(request.getRequestURI(), "UTF-8");
if (request.getQueryString() != null) from += "?" + request.getQueryString();
response.sendRedirect("login.jsf?from=" + from);
}
将其作为隐藏字段嵌入登录表单中(是的,使用纯HTML/JSTL,JSF 1.x在这里没有帮助):
<input type="hidden" name="from" value="${fn:escapeXml(param.from)}" />
在登录方法中,检查它是否存在并进行相应处理:
public String login() {
// ...
String from = externalContext.getRequestParameterMap().get("from");
if (from != null && !from.isEmpty()) {
externalContext.redirect(from);
return null;
} else {
return "home"; // Default landing page after login.
}
}
下面是一个在过滤器中将其作为会话属性传递的示例:
if (user == null) {
String from = request.getRequestURI();
if (request.getQueryString() != null) from += "?" + request.getQueryString();
request.getSession().setAttribute("from", from);
response.sendRedirect("login.jsf");
}
这不需要隐藏字段。在登录方法中,检查它是否存在并进行相应处理:
public String login() {
// ...
String from = externalContext.getSessionMap().get("from");
if (from != null && !from.isEmpty()) {
externalContext.getSessionMap().remove("from");
externalContext.redirect(from);
return null;
} else {
return "home"; // Default landing page after login.
}
}
JSF和URL不能很好地协同工作:JSF URL不可添加书签,URL与您正在查看的页面相比总是晚一页,等等…因此,在您的情况下,您不应该考虑URL,而应该考虑视图(.xhtml)文件。
解决问题的一种方法是在步骤2创建一个会话管理的bean,该bean存储当前视图(以及相关联的bean参数(如果有的话))。一旦用户登录,就会检查该会话bean是否存在,如果存在,则将用户重定向到存储视图,而不是重定向到标准的登录后视图。这是通过在doSignIn方法中返回"viewName"来完成的。