2012-06-12 8 views
3

Spring MVC 애플리케이션에서 DelegatingFilterProxy로 구현 된 필터가 있으며 두 번 호출됩니다. 나는 무슨 일이 일어나고 있는지 모른다. 모든 컨텍스트가 root-context.xml에 있고 내 servlet-context.xml이 비어 있기 때문에 Spring 컨텍스트가 두 번 만들어지지 않을 것이라고 확신합니다. DelegatingFilterProxy가 Spring 보안이없는 Spring MVC 애플리케이션에서 두 번 호출됩니다.

내 web.xml의 :

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

    <display-name>cheapig</display-name> 

    <!--Definição do Contexto Global do Container do Spring com recursos (beans) que são compartilhados com 
    TODOS os Servlets e Filtros --> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/spring/root-context.xml</param-value> 
    </context-param> 

    <!-- Cria o container do Spring compartilhado com todos os Servlets e Filtros --> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <listener> 
     <display-name>sessionListener</display-name> 
     <listener-class>br.com.cheapig.util.SessionListener</listener-class> 
    </listener> 

    <!-- Filtro para controlar acesso --> 
    <filter> 
    <filter-name>cheapigFilter</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
    </filter> 

    <filter-mapping> 
     <filter-name>cheapigFilter</filter-name> 
     <url-pattern>/*</url-pattern> 

    </filter-mapping> 

    <!-- Definição do Servlet que processa todos os requests da aplicação. Como se está utilizando 
    o Framework Spring, o servlet é o DispatcherServlet. --> 
    <servlet> 
     <servlet-name>cheapig</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/spring/cheapig/servlet-context.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <!-- Mapeamento dos Servlets e URLs -->  
    <servlet-mapping> 
     <servlet-name>cheapig</servlet-name> 
     <url-pattern>/cheapig/*</url-pattern> 
    </servlet-mapping> 

    <error-page> 
     <error-code>404</error-code> 
     <location>/WEB-INF/view/util/layout_404.jsp</location> 
    </error-page> 

    <error-page> 
     <error-code>405</error-code> 
     <location>/WEB-INF/view/util/layout_405.jsp</location> 
    </error-page> 

    <error-page> 
     <error-code>500</error-code> 
     <location>/WEB-INF/view/util/layout_500.jsp</location> 
    </error-page> 

    <session-config> 
     <session-timeout>30</session-timeout> 
    </session-config> 

</web-app> 

내 루트 컨텍스트 (즉, 서블릿의 context.xml 기억이 주석) :

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
     http://www.springframework.org/schema/aop  
     http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd 
     "> 
    <mvc:resources mapping="/resources/**" location="/resources/" /> 

    <!-- Imports user-defined @Controller beans that process client requests --> 
    <import resource="cheapig/controllers.xml" /> 
    <import resource="cheapig/hibernateMySQL5.xml"/>  
    <import resource="cheapig/integracaoTiles2.xml"/> 
    <import resource="cheapig/servicoEmail.xml"/> 

    <mvc:annotation-driven/> 
    <context:component-scan base-package="br.com.cheapig" /> 
    <task:annotation-driven/> 

    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory"/>  
    </bean> 

    <!-- Root Context: defines shared resources visible to all other web components --> 
    <!-- Configurações de Internacionalização --> 
    <bean id="messageSource" 
     class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
     <property name="basename" value="classpath:messages" /> 
     <property name="defaultEncoding" value="latin1" /> 
    </bean> 

    <bean id="localeResolver" 
     class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> 
     <property name="defaultLocale" value="pt" /> 
    </bean> 

    <!-- Mapeamento da view "rssViewer" para o bean "rssViewer" --> 
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> 
    <bean id="rssViewer" class="br.com.cheapig.servico.CustomRssViewer" /> 



    <bean id="multipartResolver" 
     class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
     <!-- one of the properties available; the maximum file size in bytes --> 
     <property name="maxUploadSize" value="3145728" /> 
     <property name="maxInMemorySize" value="3145728"></property> 
    </bean> 

    <bean id="velocityEngine" 
     class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> 
     <property name="velocityProperties"> 
      <value> 
       resource.loader=file 
       file.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader 
      </value> 
     </property> 
    </bean> 
    <!-- <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> 
     <property name="velocityProperties"> <value> resource.loader=class class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader 
     </value> </property> <property name="resourceLoaderPath"> <value>/WEB-INF/velocity</value> 
     </property> </bean> --> 



    <!-- <bean id="controleAcesso" class="br.com.cheapig.seguranca.ControleAcesso"> 
     <bean id="cheapigFilter" class="br.com.cheapig.seguranca.SegurancaFilter" 
     > <property name="controleAcesso" ref="controleAcesso" /> <property name="localeResolver" 
     ref="localeResolver" /> </bean> --> 

</beans> 

내 필터 :

package br.com.cheapig.seguranca; 

import java.io.IOException; 
import java.util.Date; 
import java.util.Locale; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.i18n.LocaleContextHolder; 
import org.springframework.stereotype.Component; 
import org.springframework.web.filter.OncePerRequestFilter; 
import org.springframework.web.servlet.LocaleResolver; 

import br.com.cheapig.controlador.HistoricoVisitasController; 
import br.com.cheapig.dominio.HistoricoVisitas; 
import br.com.cheapig.dominio.Usuario; 
import br.com.cheapig.exception.ControleAcessoException; 
import br.com.cheapig.util.CheapigUtil; 
import br.com.cheapig.util.ConstantesAmbiente; 
import br.com.cheapig.util.ConstantesGenericas; 
import br.com.cheapig.util.ConstantesHistoricoVisitas; 
import br.com.cheapig.util.ConstantesSessao; 
import br.com.cheapig.util.WorkflowUtil; 
import br.com.cheapig.workflow.Request; 

/** 
* Classe responsável por fazer a filtragem do controle de acesso aos recursos do site 
* 
* @author Guilherme Macedo 
* @since Apr 30, 2012 
*/ 
@Component(value = "cheapigFilter") 
public class SegurancaFilter extends OncePerRequestFilter { 

    @Autowired 
    private ConstantesAmbiente constantesAmbiente; 

    @Autowired 
    private LocaleResolver localeResolver; 

    @Autowired 
    private ControleAcesso controleAcesso; 

    @Autowired 
    private HistoricoVisitasController historicoVisitasController; 

    /** 
    * Cria um novo objeto SegurancaFilter 
    */ 
    public SegurancaFilter() { 
     super(); 
    } 

    /** 
    * @see org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.servlet.http.HttpServletRequest, 
    *  javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain) 
    */ 
    @SuppressWarnings("unchecked") 
    @Override 
    protected void doFilterInternal(HttpServletRequest pRequest, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Locale locale = new Locale("pt", "br"); 
     this.localeResolver.setLocale(pRequest, response, locale); 
     LocaleContextHolder.setLocale(locale); 
     String path = pRequest.getRequestURI().substring(pRequest.getContextPath().length()); 
     String uri = pRequest.getRequestURI(); 

     HttpSession vSession = pRequest.getSession(); 
     String appId = (String) vSession.getAttribute("facebookAppId"); 
     if(appId == null || appId.isEmpty()){ 
      vSession.setAttribute("facebookAppId", this.constantesAmbiente.getFacebookAppId()); 
     } 

     if (path.startsWith("/resources") || path.startsWith("/css")) { 
      filterChain.doFilter(pRequest, response); // Goes to default servlet. 
      System.out.println("resources"); 
     } else { 
      System.out.println("uri: "+uri); 
      this.salvaVisita(pRequest); 

      if (uri.equals("/") || uri.equals("/cheapig/")) { 
       pRequest.getSession().setAttribute("loadCidadeList", true); 
      } else { 
       pRequest.getSession().setAttribute("loadCidadeList", false); 
      } 
      String vUrl = uri.substring("/cheapig".length()); 
      String vLogado = (String) vSession.getAttribute(ConstantesSessao.SESSION_LOGADO); 

      if (vLogado == null) { 
       vLogado = ConstantesGenericas.SIGLA_NAO; 
       vSession.setAttribute(ConstantesSessao.SESSION_LOGADO, ConstantesGenericas.SIGLA_NAO); 
      } 

      if (vLogado.equals(ConstantesGenericas.SIGLA_SIM) && vUrl.contains("login")) { 
       String vRedirectURL = "/cheapig/"; 
       response.sendRedirect(vRedirectURL); 
      }else{ 
       Usuario vUsuario = (Usuario) vSession.getAttribute(ConstantesSessao.SESSION_USUARIO); 

       try { 
        if (vLogado.equalsIgnoreCase(ConstantesGenericas.SIGLA_NAO)) { 
         this.controleAcesso.verificaPermissoesAnonimas(vUrl); 
        } else { 
         this.controleAcesso.verificaAcesso(vUsuario, vUrl); 
        }     
        pRequest.getRequestDispatcher(uri).forward(pRequest, response); 
       } catch (ControleAcessoException e) { 
        Request vRequest = new Request(); 
        vRequest.setRequestURI(uri); 
        vRequest.setRequestURL(vUrl); 
        vRequest.setRequestParameters(WorkflowUtil.montaParametrosURLParameterMap(pRequest.getParameterMap())); 
        vRequest.setRequestMethod(pRequest.getMethod()); 
        vSession.setAttribute("COMING_REQUEST", vRequest); 
        response.sendRedirect("/cheapig/loginTela"); 
        return; 
       } 
      } 


     } 
    } 

    public ControleAcesso getControleAcesso() { 
     return this.controleAcesso; 
    } 

    public LocaleResolver getLocaleResolver() { 
     return this.localeResolver; 
    } 

    @Override 
    protected void initFilterBean() throws ServletException { 

    } 

    /** 
    * Coleta as informações do usuário e persiste no histórico de visitas 
    * 
    * @param request 
    *   HttpServletRequest 
    */ 
    private void salvaVisita(HttpServletRequest request) { 
     String locale = request.getLocale().getLanguage(); 
     String browser = CheapigUtil.identificaBrowser(request.getHeader(ConstantesHistoricoVisitas.HTTP_BROWSER)); 
     String metodo = request.getMethod(); 
     String ip = request.getRemoteAddr(); 
     String pagAcessada = request.getRequestURI(); 
     String host = request.getRemoteHost(); 

     HistoricoVisitas historico = new HistoricoVisitas(); 
     historico.setLinguagemNavegador(locale); 
     historico.setBrowser(browser); 
     historico.setDataAcesso(new Date()); 
     historico.setHost(host); 
     historico.setIpVisitante(ip); 
     historico.setPagAcessada(pagAcessada); 
     historico.setRequestMethod(metodo); 

     this.historicoVisitasController.cadastrarHistoricoVisitas(historico); 
    } 

    public void setControleAcesso(ControleAcesso controleAcesso) { 
     this.controleAcesso = controleAcesso; 
    } 

    public void setLocaleResolver(LocaleResolver localeResolver) { 
     this.localeResolver = localeResolver; 
    } 
} 

사람 나를 도울 수 있거나 나에게 힌트를 줄 수 있습니까?

미리 감사드립니다. : D

+0

이 문제점의 근본 원인을 찾아 냈습니까? 솔루션을 공유 할 수 있습니까? Thx – mihaela

+0

아니요, 아직 해결책을 찾지 못했습니다. – jguilhermemv

답변

1

아마도 리디렉션에 문제가 있습니까?

doFilterInternal 구현에 따르면 특정 조건에서 리디렉션을 수행하고 있습니다. 리디렉션은 새 요청을 생성하므로 필터는 두 번째로 호출됩니다.

2

이 문제의 유일한 논리적 인 원인은 필터가 OncePerRequestFilter을 구현하고 있기 때문에 여러 요청이 있다는 것입니다.

가능한 원인은 리디렉션과 이벤트 버블 링입니다 (예 : onclick 기능이있는 다른 요소가있는 요소를 클릭).

2

왜 필터가 두 번 호출됩니다 생각하십니까? 디버거에 중단 점이 있습니까? 아니면 로그에 표시됩니까?

필자가 비슷한 문제 (필자의 디버거 중단 점이 필터에 두 번 부딪쳤다.)가 발생했을 때 브라우저가 클릭당 2 회의 요청을 한 것으로 나타났습니다. 실제 페이지 1 개, favicon.ico 개 기타 (북마크/즐겨 찾기 또는 Google 크롬의 URL 표시 줄).

0

내 문제는 내 필터 클래스에 @WebFilter 주석이 있다는 것입니다.

관련 문제