Login com Filtro, {Cannot forward after response has been committed } -HELP!

Pessoal, meu primeiro topico, espero que possam me ajudar.

Estou criando um site com login, estou usando Filter para tratar a sessão do login.

classe do filtro, FiltroLogin:

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package filtros;

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

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
*

  • @author Rodrigo
    */
    public class FiltroLogin implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
    System.out.println(“Filter sendo executado - FILTRO LOGIN”);

      HttpServletRequest req = (HttpServletRequest) request;
      HttpServletResponse resp = (HttpServletResponse) response;
      HttpSession session = req.getSession();
    
      if (session.getAttribute("usuarioLogado") != null) {
          System.out.println("AQUI LOGADO");
          chain.doFilter(request, response);
      } else {
          System.out.println("AQUI NAO LOGADO");
          resp.sendRedirect("login.jsp");
          //request.getRequestDispatcher("/LoginServlet").forward(request, response);
      }
    

    }

    public void init(FilterConfig config) throws ServletException {

    }

    public void destroy() {
    //add code to release any resource
    }
    }
    [/code]

Até aonde eu encontrei no google, está correto, a classe de filtro,
a ideia é simples, toda vez q for solicitada uma página, passa pelo filtro e ve se já existe usuário logado, se existir, tudo bem, chama o chain e continua o site, se não, manda o usuário para a tela de login.

Porem quando eu mando executar, em qualquer página que eu abro o firefox dá uma mensagem de erro:

Já tentei trocar de login.jsp para o servlet /LoginServlet mesmo assim não funciona, ele não dá o erro do firefox, mas tambêm não mostra página nenhuma.

ja tentei trocar de redirect para o dispatcher, como ta em comentário ali e não deu.

web.xml

<filter> <filter-name>filtroz</filter-name> <filter-class>filtros.FiltroLogin</filter-class> </filter> <filter-mapping> <filter-name>filtroz</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

Servlet do login LoginServlet:

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package controller;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.DAO.UsuarioDAO;
import model.Usuario;

/**
*

  • @author Rodrigo
    */
    public class LoginServlet extends HttpServlet {

    /**

    • Processes requests for both HTTP GET and POST methods.

    • @param request servlet request

    • @param response servlet response

    • @throws ServletException if a servlet-specific error occurs

    • @throws IOException if an I/O error occurs
      */
      protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      String jsp = “”;
      String login = request.getParameter(“login”);
      String senha = request.getParameter(“senha”);

      Usuario usr = new Usuario();
      usr.setLogin(login);
      usr.setSenha(senha);

      UsuarioDAO usrDAO = new UsuarioDAO();

      try {
      boolean us = usrDAO.validarLogin(usr);
      if (us) {
      request.getSession().setAttribute(“usuarioLogado”, usr);
      jsp = “/PrincipalServlet”;

       } else {
      
           jsp = "/erro.jsp";
       }
      

      } catch (Exception e) {
      e.printStackTrace();
      jsp = “”;
      }

      request.getRequestDispatcher(jsp).forward(request, response);
      //response.sendRedirect(“principal.jsp”);

    }

    //
    /**

    • Handles the HTTP GET method.
    • @param request servlet request
    • @param response servlet response
    • @throws ServletException if a servlet-specific error occurs
    • @throws IOException if an I/O error occurs
      */
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      //response.sendRedirect(“login.jsp”);

    }

    /**

    • Handles the HTTP POST method.
    • @param request servlet request
    • @param response servlet response
    • @throws ServletException if a servlet-specific error occurs
    • @throws IOException if an I/O error occurs
      */
      @Override
      protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      processRequest(request, response);
      }

    /**

    • Returns a short description of the servlet.
    • @return a String containing servlet description
      */
      @Override
      public String getServletInfo() {
      return “Short description”;
      }//
      }
      [/code]

Espero q possam me ajudar, obrigado.

Não esqueça que a página de login não dever ser “filtrada”.

Abraço,

fred

[quote=fre_d]
Não esqueça que a página de login não dever ser “filtrada”.

Abraço,

fred[/quote]

Como eu trato? pensei q a página de login tambêm deveria ser filtrada, ia ser enviada para ela mesmo, mas iria.

Abs.

Cara, esse seu chain.doFilter está estranho heim.

O Chain num filtro funciona assim :

Você deve entrar no método do filtro, faz todos os processos e PASSAR PELO chain.doFilter().
Da maneira que você deixou no seu código, ele só passa pelo doFilter quando uma determinada condição for verdadeira. Talvez seja por isso que fique uma tela branca pra você:
Sua condição é falsa, mas e o método doFilter, onde entra?
Até onde eu saiba, você é obrigado a chamar sempre o método doFilter num Filtro de uma Srevlet (corrijam-me se eu estiver errado).


public class FiltroLogin implements Filter {   
  
    public void doFilter(ServletRequest request, ServletResponse response,   
            FilterChain chain) throws IOException, ServletException {   
                 //faz seus processamentos aqui...
                  
                //independentemente do resultado, chama o doFilter do chain.
                 chain.doFilter();

                //mais alguma coisa aqui na volta (se vc quiser)
              
         }

Geralmente, quando eu quero exibir uma determinada mensagem ou tela pro usuário, eu seto um atributo na request e recupero no jsp, pra fazer algum if.
Tenta aí. Flw.

[quote=oddy.silva]Cara, esse seu chain.doFilter está estranho heim.

O Chain num filtro funciona assim :

Você deve entrar no método do filtro, faz todos os processos e PASSAR PELO chain.doFilter().
Da maneira que você deixou no seu código, ele só passa pelo doFilter quando uma determinada condição for verdadeira. Talvez seja por isso que fique uma tela branca pra você:
Sua condição é falsa, mas e o método doFilter, onde entra?
Até onde eu saiba, você é obrigado a chamar sempre o método doFilter num Filtro de uma Srevlet (corrijam-me se eu estiver errado).


public class FiltroLogin implements Filter {   
  
    public void doFilter(ServletRequest request, ServletResponse response,   
            FilterChain chain) throws IOException, ServletException {   
                 //faz seus processamentos aqui...
                  
                //independentemente do resultado, chama o doFilter do chain.
                 chain.doFilter();

                //mais alguma coisa aqui na volta (se vc quiser)
              
         }

Geralmente, quando eu quero exibir uma determinada mensagem ou tela pro usuário, eu seto um atributo na request e recupero no jsp, pra fazer algum if.
Tenta aí. Flw.[/quote]

Eu fiz baseado no comentário deste cara aqui: http://www.guj.com.br/java/145869-como-pegar-uma-pagina-jsp-no-filtro-de-servlet-resolvido#786402

e neste site aqui: http://www.guj.com.br/java/145869-como-pegar-uma-pagina-jsp-no-filtro-de-servlet-resolvido#786402
nessa parte:

public void doFilter(ServletRequest req, ServletResponse res,

                  FilterChain chain) throws IOException, ServletException {

            HttpSession session = ((HttpServletRequest)req).getSession();

            Usuario usuario = (Usuario)session.getAttribute("usuario");

            if(usuario==null){

                  session.setAttribute("msg","Você não está                              logado no sistema!");

                  ((HttpServletResponse)res).sendRedirect("../index.jsp");

            }else{

                  chain.doFilter(req, res);

            }

      }

Testei por o chain depois, voltou o erro do firefox de redirecionamento incorreto :frowning:

O meu é assim:

[code]public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    String url = req.getRequestURL().toString();
    Emitente emitente = (Emitente) req.getSession().getAttribute("usuario");
    if (emitente == null) {
        if (url.contains("movimentos") || url.contains("cadastros")) {
            resp.sendRedirect("../login.nfe");
        }
    }
    try {
        chain.doFilter(request, response);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}

[/code]

Talvez ajude em algo.

[quote=altitdb]O meu é assim:

[code]public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    String url = req.getRequestURL().toString();
    Emitente emitente = (Emitente) req.getSession().getAttribute("usuario");
    if (emitente == null) {
        if (url.contains("movimentos") || url.contains("cadastros")) {
            resp.sendRedirect("../login.nfe");
        }
    }
    try {
        chain.doFilter(request, response);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}

[/code]

Talvez ajude em algo.[/quote]

Boa cara, funcionou!

só alterei o if para

if (!(url.contains("login"))) { resp.sendRedirect("/TesteLogin/login.jsp"); }

Agora, uma outra duvida, testando colocar a url direto no browser, por exemplo http://localhost:8080/TesteLogin/principal.jsp
ele está voltando para a login.jsp, ta correto, mas tá lançando exeception, era para lançar mesmo?

org.apache.jasper.JasperException: java.lang.NullPointerException
        at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:491)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at filtros.FiltroLogin.doFilter(FiltroLogin.java:41)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859)
        at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1555)
        at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
        at org.apache.jsp.principal_jsp._jspService(principal_jsp.java:83)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
        ... 18 more

Ai então fui testar o login, e coloco o usuário e senha e mando logar, está saindo a seguinte exception:

java.lang.IllegalStateException: Cannot forward after response has been committed
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
        at controller.LoginServlet.processRequest(LoginServlet.java:58)
        at controller.LoginServlet.doPost(LoginServlet.java:88)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at filtros.FiltroLogin.doFilter(FiltroLogin.java:41)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859)
        at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1555)
        at java.lang.Thread.run(Thread.java:619)

na linha:

request.getRequestDispatcher(jsp).forward(request, response);

isso é uma linha do metodo do Servlet:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        String jsp = "";
        String login = request.getParameter("login");
        String senha = request.getParameter("senha");

        Usuario usr = new Usuario();
        usr.setLogin(login);
        usr.setSenha(senha);

        UsuarioDAO usrDAO = new UsuarioDAO();

        try {
            boolean us = usrDAO.validarLogin(usr);
            if (us) {
                request.getSession().setAttribute("usuarioLogado", usr);
                jsp = "/PrincipalServlet";

            } else {

                jsp = "/erro.jsp";
            }

        } catch (Exception e) {
            e.printStackTrace();
            jsp = "";
        }

        request.getRequestDispatcher(jsp).forward(request, response);
        //response.sendRedirect("principal.jsp");

    }

Sabes o que pode ser?

Vlw.

Tenta usar sem essa linha do erro…

O que você faz com ela?

[quote=altitdb]Tenta usar sem essa linha do erro…

O que você faz com ela?[/quote]

è que quando submeter o form de login, com usuário e senha, eu verifico se é um user válido, se for, ele manda para a proxima tela, a principal, aonde vai ficar menu e etc, se não for ele vai para uma tela erro.

não é assim que se faz?

Qualquer toque é bem vindo.

edit: tirando o redirect ou dispatcher “funciona”, mas ele fica na mesma tela, de login.

Eu faço assim…

Faço o login e guardo esse user de login ou uma variavel qualquer dizendo que o login foi feito com sucesso ou não.

Se foi feito com sucesso eu deixo acessar as pagina, se nao volta para o login novamente.

//login é a variavel que fala se é logado ou não.
if(login.equals("naologado") {
//vejo se o user ta acessando movimentos ou cadastros
 if (url.contains("movimentos") || url.contains("cadastros")) {  
                //se tiver e como nao vai estar com permissao ele vai pro login
                 resp.sendRedirect("../login.jsf");  
     }  

}

Trabalho assim, depois pretendo por o SPRING SECURITY.

[quote=altitdb]Eu faço assim…

Faço o login e guardo esse user de login ou uma variavel qualquer dizendo que o login foi feito com sucesso ou não.

Se foi feito com sucesso eu deixo acessar as pagina, se nao volta para o login novamente.

//login é a variavel que fala se é logado ou não.
if(login.equals("naologado") {
//vejo se o user ta acessando movimentos ou cadastros
 if (url.contains("movimentos") || url.contains("cadastros")) {  
                //se tiver e como nao vai estar com permissao ele vai pro login
                 resp.sendRedirect("../login.jsf");  
     }  

}

Trabalho assim, depois pretendo por o SPRING SECURITY. [/quote]

Até ai tudo bem, acho que o problema não é mais no Filtro, acho que deu certo o que você fez.

O erro parece ser na hora que eu submeto o form de login,

quando submeto, a action do form ta num servlet, o servlet criar o usuario e coloca em uma session, ai então pode-se logar e ir para a página principal.

ai na hora de enviar para principal eu uso o:

request.getRequestDispatcher(jsp).forward(request, response);

ou

response.sendRedirect("principal.jsp");

sacou?

Saquei…

você tentou debugar??

[quote=altitdb]Saquei…

você tentou debugar??

[/quote]

Tentei :frowning:

agora o problema é:

java.lang.IllegalStateException: Cannot forward after response has been committed
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
        at controller.LoginServlet.processRequest(LoginServlet.java:59)
        at controller.LoginServlet.doPost(LoginServlet.java:88)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at filtros.FiltroLogin.doFilter(FiltroLogin.java:43)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859)
        at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1555)
        at java.lang.Thread.run(Thread.java:619)

Esse erro eu já não conheço! =/

[quote=altitdb]Esse erro eu já não conheço! =/
[/quote]

Tambêm não sei :frowning:

tentei por o flush e o close como neste topico aqui: http://www.guj.com.br/java/38402-illegalstateexception-cannot-forward-after-response-has-been-committed

mas não deu certo.

Algueeem?