admin-showcase icon indicating copy to clipboard operation
admin-showcase copied to clipboard

Disable AdminFilter

Open JGabriel-SL opened this issue 1 year ago • 0 comments

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 ;(

LoginFilter:


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"));
    }
}

JGabriel-SL avatar Apr 24 '24 12:04 JGabriel-SL