Hi, i'm actually try to overwrite the AdminFilter, 'cause i need access some pages without user do the login, example, info pages. So, I trying to create a LoginFilter and config in the web.xml:
<filter>
<filter-name>Loginfilter</filter-name>
<filter-class>br.com.portaltbm.infra.security.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Loginfilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
the LoginFilter run, but the AdminFilter too. The problem is, i add in LoginFilter to ignore the resources to redirect for the page testePage.xhtml, but doens't work ;(
package br.com.portaltbm.infra.security;
import com.github.adminfaces.template.config.AdminConfig;
import com.github.adminfaces.template.session.AdminSession;
import com.github.adminfaces.template.util.Constants;
import javax.inject.Inject;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.github.adminfaces.template.util.Assert.has;
/**
* Based on https://github.com/conventions/core/blob/master/src/main/java/org/conventionsframework/filter/ConventionsFilter.java
* Created by rafael-pestano on 07/01/17.
*
* This filter controls when user must be redirected to logon or index page
* and saves current url to redirect back when session expires
*/
@WebFilter(urlPatterns = {"/*"})
public class LoginFilter implements Filter {
private static final String FACES_RESOURCES = "/javax.faces.resource";
private static final Logger log = Logger.getLogger(LoginFilter.class.getName());
private boolean disableFilter;
private String loginPage;
private String indexPage;
private String testePage;
private String redirectPrefix;
private String lastPage = "";
@Inject
AdminSession adminSession;
@Inject
AdminConfig adminConfig;
private final List<String> ignoredResources = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) {
String disableAdminFilter = filterConfig.getServletContext().getInitParameter(Constants.InitialParams.DISABLE_FILTER);
if (adminConfig.isDisableFilter() || has(disableAdminFilter) && Boolean.valueOf(disableAdminFilter)) {
disableFilter = true;
}
if (!disableFilter) {
try {
loginPage = filterConfig.getServletContext().getInitParameter(Constants.InitialParams.LOGIN_PAGE);
testePage = "testePage.xhtml";
if (!has(loginPage)) {
loginPage = has(adminConfig) ? adminConfig.getLoginPage() : Constants.DEFAULT_LOGIN_PAGE;
}
String errorPage = filterConfig.getServletContext().getInitParameter(Constants.InitialParams.ERROR_PAGE);
if (!has(errorPage)) {
errorPage = Constants.DEFAULT_ERROR_PAGE;
}
indexPage = filterConfig.getServletContext().getInitParameter(Constants.InitialParams.INDEX_PAGE);
if (!has(indexPage)) {
indexPage = has(adminConfig) ? adminConfig.getIndexPage() : Constants.DEFAULT_INDEX_PAGE;
}
//removes leading '/'
errorPage = errorPage.startsWith("/") ? errorPage.substring(1) : errorPage;
loginPage = loginPage.startsWith("/") ? loginPage.substring(1) : loginPage;
indexPage = indexPage.startsWith("/") ? indexPage.substring(1) : indexPage;
ignoredResources.add("/" + loginPage.substring(0, loginPage.lastIndexOf(".")));//we need leading slash for ignoredResources
ignoredResources.add("/" + errorPage.substring(0, errorPage.lastIndexOf(".")));
ignoredResources.add("/" + testePage.substring(0, testePage.lastIndexOf(".")));
String configuredResouces = adminConfig.getIgnoredResources();
if (has(configuredResouces)) {
this.ignoredResources.addAll(Arrays.asList(configuredResouces.split(",")));
for (String ignoredResource : ignoredResources) {
if (!ignoredResource.startsWith("/")) { //we need leading slash for ignoredResources beucase getServletPath (in this#skipResource) returns a string with leading slash
ignoredResources.set(ignoredResources.indexOf(ignoredResource), "/" + ignoredResource);
}
}
}
} catch (Exception e) {
log.log(Level.SEVERE, "problem initializing admin filter", e);
}
}
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
if (disableFilter) {
chain.doFilter(req, resp);
return;
}
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String requestedPage = request.getRequestURI();
if (requestedPage.endsWith(testePage)) {
// Permite o acesso direto à página testePage sem verificar o login
chain.doFilter(req, resp);
return;
}
if (request.getRequestURI().equals(request.getContextPath() + "/")
|| (adminSession.isLoggedIn() && request.getRequestURI().endsWith(loginPage))) {
response.sendRedirect(getRedirectPrefix(request) + request.getContextPath() + "/" + indexPage);
return;
}
if (request.getRequestURI().contains(request.getContextPath() + "/public/") || shouldIgnoreResource(request.getServletPath())) {
chain.doFilter(req, resp);
return;
}
if (skipResource(request, response) || adminSession.isLoggedIn()) {
if (!adminSession.isUserRedirected() && adminSession.isLoggedIn() && has(request.getHeader("Referer")) && request.getHeader("Referer").contains("?page=")) {
adminSession.setUserRedirected(true);
String pageFromURL = request.getContextPath() + extractPageFromURL(request.getHeader("Referer"));
log.info("Redirecting user back to " + pageFromURL);
response.sendRedirect(getRedirectPrefix(request) + pageFromURL);
return;
}
try {
chain.doFilter(req, resp);
} catch (FileNotFoundException e) {
log.log(Level.WARNING, "File not found", e);
response.sendError(404);
}
} else { //resource not skipped (e.g a page that is not logon page) AND user not logged in
redirectToLogon(request, (HttpServletResponse) resp);
return;
}
}
private String extractPageFromURL(String referer) {
String page = referer.substring(referer.indexOf("page=") + 5);
try {
return URLDecoder.decode(page, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.log(Level.WARNING, "Could not extract page from url", e);
return indexPage;
}
}
@Override
public void destroy() {
}
/**
* skips faces-resources, index, error or logon pages
*
* @param request
* @return true if resource must be skipped by the filter false otherwise
*/
private boolean skipResource(HttpServletRequest request, HttpServletResponse response) {
String path = request.getServletPath();
if (path.contains(".")) {
path = path.substring(0, path.lastIndexOf("."));
}
boolean skip = path.startsWith(FACES_RESOURCES) || shouldIgnoreResource(path) || response.getStatus() == HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
return skip;
}
private void redirectToLogon(HttpServletRequest request, HttpServletResponse response) {
try {
String referer = request.getHeader("Referer");
String recoveryUrlParams;
//get request parameters
if (has(referer) && referer.contains("?")) {
recoveryUrlParams = referer.substring(referer.lastIndexOf("?") + 1);
} else {
recoveryUrlParams = request.getQueryString();
}
//saves page where user were
String requestedPage = request.getRequestURI();
StringBuilder recoveryUrl = null;
if ((!testePage.equals(requestedPage) || !loginPage.equals(requestedPage)) && requestedPage.contains(".")) {
if (requestedPage.startsWith(request.getContextPath())) {
requestedPage = requestedPage.replaceFirst(request.getContextPath(), "");
}
recoveryUrl = new StringBuilder(requestedPage);
if (has(recoveryUrlParams)) {
recoveryUrl.append("?").append(recoveryUrlParams);
}
}
/*
if saved page is not null and is not index page then send user to logon page and save
/ previous page in url param named 'page'
*/
String redirectUrl = "";
// if (requestedPage.equals("/testePage.xhtml")) {
// redirectUrl = request.getContextPath() + "/" + testePage + (has(recoveryUrl) &&
// isValidRecoveryUrl(recoveryUrl) ? "?page=" + URLEncoder.encode(recoveryUrl.toString(), "UTF-8") : "");
// } else {
redirectUrl = request.getContextPath() + "/" + loginPage + (has(recoveryUrl) &&
isValidRecoveryUrl(recoveryUrl) ? "?page=" + URLEncoder.encode(recoveryUrl.toString(), "UTF-8") : "");
// }
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
//redirect on ajax request: //http://stackoverflow.com/questions/13366936/jsf-filter-not-redirecting-after-initial-redirect
response.setContentType("text/xml");
response.getWriter()
.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", redirectUrl);
} else {//normal redirect
response.sendRedirect(getRedirectPrefix(request) + redirectUrl);
}
} catch (Exception e) {
log.log(Level.SEVERE, "Could not redirect to " + loginPage, e);
}
}
/**
* Skip error pages, login and index page as recovery url because it doesn't make sense redirecting user to such pages
*
* @param recoveryUrl
* @return
*/
private boolean isValidRecoveryUrl(StringBuilder recoveryUrl) {
String pageSuffix = adminConfig.getPageSufix();
return !recoveryUrl.toString().contains(Constants.DEFAULT_INDEX_PAGE.replace("xhtml", pageSuffix)) && !recoveryUrl.toString().contains(Constants.DEFAULT_ACCESS_DENIED_PAGE.replace("xhtml", adminConfig.getPageSufix()))
&& !recoveryUrl.toString().contains(Constants.DEFAULT_EXPIRED_PAGE.replace("xhtml", pageSuffix)) && !recoveryUrl.toString().contains(Constants.DEFAULT_OPTIMISTIC_PAGE.replace("xhtml", adminConfig.getPageSufix()))
&& !recoveryUrl.toString().contains(Constants.DEFAULT_LOGIN_PAGE.replace("xhtml", adminConfig.getPageSufix()));
}
/**
* @param path
* @return true if requested path starts with a ignored resource (configured in admin-config.properties)
*/
private boolean shouldIgnoreResource(String path) {
for (String ignoredResource : ignoredResources) {
if (path.startsWith(ignoredResource)) {
return true;
}
}
return false;
}
private String getRedirectPrefix(HttpServletRequest request) {
if(redirectPrefix == null) {
String url = request.getRequestURL().toString();
String uri = request.getRequestURI();
int offset = url.indexOf(uri);
redirectPrefix = url.substring(0, offset);
if(useHttps(request)) {
log.log(Level.WARNING,"Changing request scheme to https.");
redirectPrefix = redirectPrefix.replace("http:","https:");
}
}
return redirectPrefix;
}
private static boolean useHttps(HttpServletRequest request) {
String protocolProperty = System.getProperty("admin.protocol", System.getenv("admin.protocol"));
String protoHeader = request.getHeader("X-Forwarded-Proto");
return request.isSecure() || (protoHeader != null && protoHeader.toLowerCase().equals("https"))
|| (protocolProperty != null && protocolProperty.toLowerCase().equals("https"));
}
}