A filter to get Java

Filter: Filter

introduction

We can use the technology front, make some simple login and register with the database to achieve the data CRUD of Demo, the basic program is up and running, but there is a major security problem, it landed rights verification, Generally landing correct process is this: the requesting user client -> background judge whether the login -> is not restricted, otherwise jump back to the login page, and log on to determine whether we've learned Header acquired referer so as to then judge of the effect of anti-hotlinking similar feeling that a judgment from the filter look, while filter is a better solution to this technical problem, of course, the powerful more than that, here we take it a say!

(A) Overview of the filter

Filter, by definition a thing is to play the role of screening filter, but compared to the real life of the filter, where the filter the filtered object is a web resource for client access can also be understood as a pre-treatment means, the interception of resources, which we believe will filter impurities (user-defined), in line with the conditions of release, does not meet the intercept them

Of course, both filters can intercept request, can also block the return of the response, we look at a map

(B) a first filter program

The nature of the filter is a Java class that implements the Filter interface

Let's create a class of their own, to achieve Filter interface (javax.servlet), all of these methods to rewrite

@WebFilter("/*")
public class FilterDemo1 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //放行代码
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
    }

}

Methods Let us not explore them, we look at how to configure filter

(C) filter configuration

The first: web.xml configuration

<filter>
    <filter-name>filterDemo1</filter-name>
    <filter-class>package cn.ideal.web.filter.FilterDemo1</filter-class>
</filter>

<filter-mapping>
    <filter-name>filterDemo1</filter-name>
    <!-- 拦截路径 -->
    <url-pattern>/*</url-pattern>
</filter-mapping>

filter

<filter-name></filter-name> : Specifies the filter name

<filter-class></filter-class> : Specifies the filter full class name (with the package name)

filter-mapping

<filter-name></filter-name> : Tag here is to filter corresponding to the above names, corresponding to point to a file

<url-pattern></url-pattern>: Set the filter to intercept the path ※ here to decide what kind of resources will be blocked filter processing

Intercept path settings

format Explanation
/test.jsp Only test.jsp access this resource will be executed when the filter
/test/* All the resources you time to implement the filter under test access
*.jsp Jsp format when all resources are accessed, the execution filter
/* Any resources being accessed, are the implementation of the filter

Since the filter is provided in the more general setting number, so in general the use of /*this format, but may be selected according to demand

Interception way configuration: dispatcher

Interception arranged which is in the form of resource being accessed , there are so few properties

  • REQUEST: default browser directly request resources

  • FORWARD: Forwarding access to resources: RequestDispatcher.forward ();

  • INCLUDE: includes access to the resource: RequestDispatcher.include ();

  • ERROR: Error Jump Resources: to be called declarative exception handling mechanism when

Supplementary : declarative exception handling, ie: in web.xml to determine how different types of exceptions will be handled by configuration, which finally jump to the page, that is, we often see some of the 404 error page

<error-page>
    <!--异常的类-->
         <exception-type>xxx</exception-type>
    <!--异常发生时跳转的页面-->
        <location>xxx</location>
</error-page>

The second: use annotations Configuration

Servlet with a similar configuration, we can specify its name and path interception

@WebFilter("filterName="FilterDemo1",urlPatters="/*")

But directly on the class declaration notes, it is clear that we do not need to specify its name, but by looking at the source code and can know, urlPatters and can be designated value, and value and can be omitted, so we can be abbreviated as

@WebFilter("/*")

To configure the dispatcher in the filter annotations, we need to set dispatcherTypes property

@WebFilter(value = "/*",dispatcherTypes ={DispatcherType.FORWARD,DispatcherType.FORWARD} )

(D) the filter life cycle

Finished configuration, here we return to the theme of said filter is a life cycle, which is above the interface and achieve the rewrite of those who

The first is the init(FilterConfig config)method and the void destroy()method, Servlet also has two methods, both of which were at server startup and shutdown is the time to create and destroy , both executed once for loading and releasing resources

In fact, it is these two methods on the basis of Servlet or well understood

Furthermore, it is the core of the way we filter:

void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)

doFilter method is our true method to intercept, through the first two parameters we can know whether Request or Respone we can also be filtering operation, then the third parameter What does it mean?

Our open source FilterChain

public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

Ok! FilterChain is an interface within the interface also defines a method doFilter, what is the meaning of its existence it?

This is a chain structure, we referred to herein as the filter chain, and its role is to configure a plurality of filters, a plurality of execution flow in the filters is such that

So, who is more filters before it after who? This is also related to our previous configuration

  • Configuration Notes: According to the comparison class name string, the first implementation of small value
    • Eg: AFilterDemo precedence over BFilterDemo
  • web.xml Configuration: <filter-mapping>Who above, who takes precedence

Simple execution flow filter

  • Execution filter

  • Performing resource after release, may be the next filter, it may be a web resource (JSP / Servlet)

  • Filter release codes executed chain.doFilter(req, resp);code below

(E) Filter application

(1) to verify login rights

Our previous knowledge has been able to meet our simple registration and registration simple, but if we know the address, access to some resources directly through the url, it is clear this is very unreasonable, so we need to verify the login status, not logged then forwarded to the login screen, you can log on free access to some pages based on login status

We write a simple simulation program, for readability, and space issues, we have omitted part of the database connection, using a fixed password

This is the index.jsp page, which is to let go of the need to access the login page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<h1>这是首页,只有登录后才能查看</h1>
</body>
</html>

This is login.jsp page, login page is very simple

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/web-test/loginServlet" method="post">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td><input type="submit" value="登录"></td>
        </tr>
    </table>
</form>
</body>
</html>

We create a domain package, write a User entity to supplement its get, set method

package cn.ideal.domain;

public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

The following code to start writing LoginServlet, which is handling login authentication issues

package cn.ideal.web.servlet;

import cn.ideal.dao.UserDao;
import cn.ideal.domain.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置编码
        request.setCharacterEncoding("utf-8");

        //获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //封装user对象
        User loginUser = new User();
        loginUser.setUsername(username);
        loginUser.setPassword(password);

        UserDao dao = new UserDao();
        User user = dao.login(loginUser);

        if (user == null){
            //登陆失败
            request.getRequestDispatcher("/failServlet").forward(request,response);
        }else{
            //登录成功
            request.getSession().setAttribute("user",user);
            request.getRequestDispatcher("/index.jsp").forward(request,response);
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

Our null depending on whether the user is equal to determine the user name and password are correct, then we you come to write about this return to the login method a User object

We created a dao layer UserDao class, some projects will be formally written in the form interface, write achieve in impl layer, in order to conceal this step we simplify

package cn.ideal.dao;

import cn.ideal.domain.User;

public class UserDao {
    public User login(User loginUser) {
        //定义真实用户名密码(代替数据库读取)
        String trueUsername = "admin";
        String truePassword = "admin";

        if (loginUser.getUsername().equals(trueUsername) && loginUser.getPassword().equals(truePassword)) {
            //登陆成功
            return loginUser;
        } else {
            return null;
        }
    }
}

The key here, which is what we are talking about the filter method, here to note is that after the successful landing, remember to write status

request.getSession().setAttribute("user",user);

package cn.ideal.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*")
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //获取资源请求路径
        String requestURI = request.getRequestURI();

        //排除包含登录确实所需要的资源,给予放行
        if (requestURI.contains("/login.jsp") || requestURI.contains("/loginServlet")) {
            chain.doFilter(request,response);
        }else{
            //不包含,即验证用户是否已经登录
            Object user = request.getSession().getAttribute("user");
            if (user != null){
                //登陆了,放行
                chain.doFilter(request,response);
            }else{
                //没有登录,跳转回登录页面
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }
        }
    }

    public void init(FilterConfig config) throws ServletException {
    }
}

(2) sensitive word filtering

If we want some of the information submitted by the user was filtered, write some code in the servlet can be considered a way, but the most appropriate or fiter, it is more common, here we use a proxy mode enhancement request in order to be sensitive to the use of filter filtered word

We will be modified on the index page just

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<h1>这是首页,只有登录后才能查看</h1>
<form action="/web-test/replaceServlet" method="post">
    <table>
        <tr>
            <td><input type="text" name="words"></td>
        </tr>
        <tr>
            <td><input type="submit" value="敏感字检测"></td>
        </tr>
    </table>
</form>
</body>
</html>

We came in to read the incoming parameters

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String words = request.getParameter("words");
        System.out.println(words);
    }
package cn.ideal.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

@WebFilter("/*")
public class ReplaceFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //创建代理对象,增强getParameter
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //判断是不是getParameter方法
                if (method.getName().equals("getParameter")){
                    //获取返回值
                    String value = (String)method.invoke(req, args);
                    if (value != null){
                        for (String s : list){
                            if (value.contains(s)){
                                value = value.replaceAll(s,"***");
                            }
                        }
                    }
                    return value;
                }
                return method.invoke(req,args);
            }
        });
        chain.doFilter(proxy_req, resp);
    }

    private List<String> list = new ArrayList<String>();

    public void init(FilterConfig config) throws ServletException {

        try {
            //获取文件真实路径
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/replace.txt");
            //读取文件
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(realPath),"UTF-8"));
            //将每一行数据添加到list中
            String line = null;
            while((line = br.readLine())!=null){
                list.add(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

end:

If there are any deficiencies, or content in the wrong place, welcome to give me a shout advice, crab everyone! ^ _ ^

If you can help, then it is to pay attention to me! (Updated series of articles will be the first time the public number)

Here we are strangers, all in the dream and work for their own ❤

Push a stick original Java technology public numbers: more than ten days over two

Guess you like

Origin www.cnblogs.com/ideal-20/p/11496091.html