Servlet filter with JSF

2019-03-02 03:05发布

I tried to configure Servlet filter with JSF. I get lot of problems here I am using PrimeFaces also.

Here is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>JsfEaxmples</display-name>
  <context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>1</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.SEPARATOR_CHAR</param-name>
    <param-value>-</param-value>
  </context-param>
  <context-param>
    <param-name>org.richfaces.skin</param-name>
    <param-value>classic</param-value>
  </context-param>
  <context-param>
    <param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
    <param-value>true</param-value>
  </context-param>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>

  </servlet-mapping>
  <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>resources.application</param-value>
  </context-param>
  <listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
  </listener>
  <filter>
  <filter-name>sessionfilter</filter-name>
  <filter-class>com.invoice.sessionfilter</filter-class>

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

  </filter-mapping>
</web-app>

First I used filter like this <url-pattern>jsf invoice system/*</url-pattern>this totally didn't work so I changed to <url-pattern>/*</url-pattern>this one responds but give lot of problems in my filtering I check these following process with filter

  1. If session doesn't exists user should be redirected to login page
  2. if session exists and if user goes to login page he should not be redirected

more over after adding filter PrimeFaces components appearance changes. After adding filter, it's not getting navigated properly.

Here is my filter code.

package com.invoice;

import java.io.IOException;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class sessionfilter implements Filter {

    String uname;

    /**
     * Default constructor.
     */
    public sessionfilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // place your code here

        // pass the request along the filter chain
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String pagerequested = req.getRequestURL().toString();
        HttpSession ses = req.getSession(true);
        //uname=(String)ses.getAttribute("uname");//null pointer exception
        if (pagerequested.contains("Login.xhtml") && uname == null)// if user logs in to this for first time
        {

            chain.doFilter(request, response);

        } else if (uname != null && pagerequested.contains("Login.xhtml")) { // if session exists and user tries to go to login page he should be redirected

            resp.sendRedirect("invoiceinfo.xhtml");

        } else if (uname == null && !pagerequested.contains("Login.xhtml")) {

            try {
                uname = (String) ses.getAttribute("uname");
                chain.doFilter(request, response);

            } catch (Exception e) {
                resp.sendRedirect("Login.xhtml");
            }
        }
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

Here is my login bean with sessionn scoped i dont use annotation here

package com.invoice;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

@SessionScoped
public class login {

    String username, userpassword, errormess, navipg;

    public String getNavipg() {
        return navipg;
    }

    public void setNavipg(String navipg) {
        this.navipg = navipg;
    }

    public String getErrormess() {
        return errormess;
    }

    public void setErrormess(String errormess) {
        this.errormess = errormess;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserpassword() {
        return userpassword;
    }

    public void setUserpassword(String userpassword) {
        this.userpassword = userpassword;
    }

    public String navigate() {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "invoice", "google");
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery("select username,password from usertable where username='" + username + "' and password='" + userpassword + "' ");
            if (rs.next()) {
                setErrormess("");
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("uname", this.username);
                navipg = "invoiceinfo";
            } else {
                setErrormess("Invalid Login credentials");
                username = "";
                navipg = "Login";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return navipg;
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        return "Login";
    }
}

My login page is

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <style type="text/css">
            .ui-panelgrid tr,
            .ui-panelgrid td {
                border: none;
            }
        </style>
    </h:head>

    <h:body>
        <h:form>
            <p:panelGrid columns="3" id="pnl" border= "0">
                <f:facet name="header"><p:graphicImage value="login.jpg"/></f:facet>
                <h:outputText value="Username"/>

                <p:inputText id="uname" value="#{login.username}" required="true" label="username"/>
                <p:message for="uname"/>

                <h:outputText value="Password"/>
                <p:password id="pass" value="#{login.userpassword}" required="true" label="password"/>
                <p:message for="pass"/>

                <p:commandButton value="Login" action="#{login.navigate}" ajax="false"/>
                <p:button value="Reset" />
            </p:panelGrid>

            <h1><h:outputText value="#{login.errormess}"/></h1>
        </h:form>
    </h:body>
</html>

I'm totally stuck here and not getting idea how to proceed with filter.

1条回答
地球回转人心会变
2楼-- · 2019-03-02 03:13

With CDI I use this. Seems to work fine. Redirects on ajax requests too.

All pages are in /secure/, except login.xhtml which are in the root.

<filter>         
    <filter-name>LoginFilter</filter-name>         
    <filter-class>...LoginFilter</filter-class>     
</filter>      
<filter-mapping>         
    <filter-name>LoginFilter</filter-name>         
    <url-pattern>/secure/*</url-pattern>     
</filter-mapping>  

Filter:

@Inject
private LoginBean loginBean;

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    // Set response headers to no-cache
    HttpServletResponse res = (HttpServletResponse) response;
    HttpServletRequest req = (HttpServletRequest) request;
    res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
    res.setDateHeader("Expires", 0); // Proxies.

    // Check if user logged in, if not redirect to login.xhtml
    if (loginBean == null || !((LoginBean) loginBean).isLoggedIn()) {
        boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));

        if (!isAjax) {
            res.sendRedirect(req.getContextPath() + "/login.xhtml"); 
        } else {
            // Redirecting an ajax request has to be done in the following way:
            // http://javaevangelist.blogspot.dk/2013/01/jsf-2x-tip-of-day-ajax-redirection-from.html
            String redirectURL = res.encodeRedirectURL(req.getContextPath() + "/login.xhtml");
            StringBuilder sb = new StringBuilder();
            sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><partial-response><redirect url=\"").append(redirectURL).append("\"></redirect></partial-response>");
            res.setCharacterEncoding("UTF-8");
            res.setContentType("text/xml");
            PrintWriter pw = response.getWriter();
            pw.println(sb.toString());
            pw.flush();
        }
    } else {
        // Let chain of filters continue;
        chain.doFilter(request, response);
    }
}

login.xhtml:

<h:body onload="PF('dlg').show()">
    <p:growl id="growl" life="5000" autoUpdate="true" showDetail="true" escape="false"/>

    <h:form>    
        <p:dialog id="dialog" header="Login" footer="..." width="400" widgetVar="dlg" closable="false" showEffect="clip" draggable="false" resizable="false" style="box-shadow: 7px 10px 5px #303030;"> 

            <p:panelGrid columns="2">
                <p:outputLabel value="Username"/>            
                <p:inputText value="#{loginBean.username}" id="username"/>            
                <p:outputLabel value="Password"/>            
                <p:password value="#{loginBean.password}" id="password"/>            
            </p:panelGrid>
            <p:commandButton  id="button" value="Login" action="#{loginBean.doLogin}" style="float:right"/> 
.... close tags

LoginBean is a simple SessionScoped CDI bean.

查看更多
登录 后发表回答