我为jsf项目创建了简单的登录系统。 在项目中,我创建过滤器以检查用户登录状态。
如果登录,请继续请求页面。
如果没有登录或会话被破坏,请重定向到登录页面
我的问题是,如果我应用过滤器,则所有h:commandLink在单击后都不会处理任何内容。但是当我删除过滤器时,一切都运行良好。
我尝试将h:commandButton与fileter一起使用,然后正常工作。
我该如何解决这个问题? 我研究了很长时间,但没有找到任何解决方案。 请帮帮我!
过滤代码:
@WebFilter(filterName = "AuthenticationFilter", urlPatterns = {"*.htm"}, dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
public class AuthenticationFilter implements Filter {
// The filter configuration object we are associated with. If
// this value is null, this filter instance is not currently
// configured.
private FilterConfig filterConfig = null;
@Inject
private AuthenticationManager authenticationManager;
public AuthenticationFilter() {
}
/**
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Throwable problem = null;
try {
HttpServletRequest req = (HttpServletRequest) request;
String requestUrl = req.getRequestURI();
String contextPath = req.getContextPath();
if(contextPath.equals("/")){
contextPath = "";
}
String jsfUrl = requestUrl.replaceFirst(contextPath, "");
if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
chain.doFilter(request, response);
}
else {
String redirectPath = contextPath+"/login.htm";
((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
}
}
catch (Throwable t) {
// If an exception is thrown somewhere down the filter chain,
// we still want to execute our after processing, and then
// rethrow the problem after that.
problem = t;
}
// If there was a problem, we want to rethrow it if it is
// a known type, otherwise log it.
if (problem != null) {
if (problem instanceof ServletException) {
throw (ServletException) problem;
}
if (problem instanceof IOException) {
throw (IOException) problem;
}
sendProcessingError(problem, response);
}
}
/**
* Return the filter configuration object for this filter.
*/
public FilterConfig getFilterConfig() {
return (this.filterConfig);
}
/**
* Set the filter configuration object for this filter.
*
* @param filterConfig The filter configuration object
*/
public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
if (filterConfig != null) {
}
}
}
Jsf代码:
<h:body>
<f:view contentType="text/html" locale="#{authenticationManager.languageCode}">
<div class="header">
<h:form id="topForm" prependId="false">
<div class="logo">
<h1><img src="#{facesContext.externalContext.requestContextPath}/resources/images/login-logo2.png" width="220" height="64"/></h1>
</div>
<ul class="navTop">
<li>
<a href="#"><span class="pictograms">f</span>#{authenticationManager.currentUser.firstName} #{authenticationManager.currentUser.lastName}</a>
</li>
<li>
<a href="#"><span class="pictograms">m</span>Messages</a>
</li>
<li class="logout">
<h:commandButton action="#{authenticationManager.logout()}" value="aaaaaaa" style="color:#fff;" />
<h:commandLink action="#{authenticationManager.logout()}" value="#{label.Logout}"/>
<h:commandLink immediate="true" action="#{authenticationManager.logout}" id="logoutLink">
<span class="pictograms">E</span>***This link is not work correctly***
</h:commandLink>
</li>
</ul>
<ui:insert name="mainmenu"/>
</h:form>
</div>
答案 0 :(得分:1)
导致您的具体问题,因为过滤器阻止了JSF默认资源jsf.js
的服务。此资源对于JSF命令链接和JSF ajax请求的运行是必需的(没有ajax的普通命令按钮才能正常工作)。
您需要从身份验证检查中排除JSF资源。您可以通过检查请求URI是否在具有ResourceHandler.RESOURCE_IDENTIFIER
(值为/javax.faces.resource
)的webapp上下文路径之后开始执行此操作。
所以,基本上:
HttpServletRequest req = (HttpServletRequest) request;
if (req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
chain.doFilter(request, response); // Let it continue.
return;
}
检查文件扩展名是笨拙的,并没有充分涵盖所有可能的资源请求。
答案 1 :(得分:0)
经过研究,我没有找到任何解决方案。 所以我采取了许多可能的方式,并找到了解释。
我使用过滤模式“* .htm”过滤所有内容,然后每个请求(如.js.htm,.css.htm,.gif.htm,.jpg.htm)都会重定向到login.htm页面。
重点是将.js.htm重定向到登录页面而不是右侧文件。 所以像jsf.js.htm这样的重要库被重定向到login.htm,这是使h:commandLink工作不正确的主要原因。
跳这会帮助像我这样的人。
try {
HttpServletRequest req = (HttpServletRequest) request;
String requestUrl = req.getRequestURI();
if(requestUrl.endsWith(".js.htm")
|| requestUrl.endsWith(".css.htm")
|| requestUrl.endsWith(".gif.htm")
|| requestUrl.endsWith(".png.htm")
|| requestUrl.endsWith(".jpg.htm")
|| requestUrl.endsWith(".jpeg.htm")){
chain.doFilter(request, response);
}
else{
String contextPath = req.getContextPath();
if(contextPath.equals("/")){
contextPath = "";
}
String jsfUrl = requestUrl.replaceFirst(contextPath, "");
if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
chain.doFilter(request, response);
}
else {
String redirectPath = contextPath+"/login.htm";
((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
}
}
}