SpringBoot 2.0 Filter 不同的實現 常見的坑


SpringBoot 2.0 不得不說的過濾器 Filter

servlet最重要的特性之一:過濾器,對訪問的路徑、資源進行限定攔截,實現特有的功能。比如URL級別的權限認證,session驗證,Referer 過濾等等操作

現在的情況是這樣的:我有一個接口,返回的是JSON數據,但如何不做限定操作,瀏覽器直接訪問該路徑的話會直接得到數據,那么用戶的信息就被泄露了。

其實就這個就是http Referer防止外鏈的操作,不懂的也沒關系,只需要知道Referer直接瀏覽器訪問是空,Submit表單提交就會有值

好了,現在我們就來實現這個過濾的操作

image


User 存儲用戶的姓名和年齡

package priv.augus.filter.controller;
/**
 * IntelliJ IDEA
 *
 * @author Augus
 * @date 2018/8/3
 */
public class User {
    private String name;

    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

通過實現接口Filter自定義我們RefererFilter的過濾器類,這里面的邏輯就是判斷Referer的值

package priv.augus.filter.controller;


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

/**
 * IntelliJ IDEA
 *
 * @author Augus
 * @date 2018/8/3
 */
public class RefererFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse res = (HttpServletResponse) servletResponse;
        String referer = req.getHeader("Referer");
        if(referer==null){
            // 為空就滾去error
            res.sendRedirect("/error");
            return;
        }
        // 有值,就繼續執行下一個過濾鏈
        filterChain.doFilter(req, res);
    }

    @Override
    public void destroy() {

    }
}

通過注解@Configuration和@Bean實現啟動服務時候加載Bean

package priv.augus.filter.controller;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * IntelliJ IDEA
 *
 * @author Augus
 * @date 2018/8/3
 */
@Configuration
public class FilterConfiguration {

    @Bean
    public FilterRegistrationBean refererFilterRegistration() {
        FilterRegistrationBean<RefererFilter> registration = new FilterRegistrationBean<>();
        //注入過濾器
        registration.setFilter(new RefererFilter());
        //過濾規則
        registration.addUrlPatterns("/user/*");
        //過濾器名稱
        registration.setName("ref");
        //過濾器順序
        registration.setOrder(1);

        return registration;
    }
}

controller層就是一個簡單的跳轉

package priv.augus.filter.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * IntelliJ IDEA
 *
 * @author Augus
 * @date 2018/8/3
 */
@Controller
@RequestMapping("/")
public class IndexController {


    @RequestMapping("/index")
    public String index(){
        return "index";
    }

    @ResponseBody
    @RequestMapping("/user/all")
    public List<User> getAllUser(){
        // 模擬從數據庫取數據返回
        User user = new User("小明",23);
        User user1 = new User("小大黃",12);
        List<User> userList = new ArrayList<>();
        userList.add(user);
        userList.add(user1);
        return userList;
    }
}

還有個Index頁面,模擬的表單提交獲取數據,我這里用的thymeleaf

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<form th:action="@{/user/all}" method="POST">
    <input type="submit" value="獲取數據">
</form>
</body>
</html>

啟動服務后

瀏覽器訪問 http://localhost:8081/user/all
image

通過表單 submit獲取的數據

image

Filter 不同的實現

@Component

剛才我的實現好了,這是一個簡單的測試用例

現在我們就來看看到底Filter是怎么加載的,現在大家在看我的例子,我這里面過濾的路徑是/user/,如果哪里不小心配置錯了,過濾的路徑是/,那么恭喜你,瀏覽器會死循環進入/erorr頁面,因為過濾器把/erorr頁面也攔截了。

有人就看到網上的案例自定義的RefererFilter上面要加上@Component注解,

@Component
public class RefererFilter implements Filter {}

現在通過日志查看有什么不同

沒有@Component
image

有@Component
image

我們可以知道得知原來加了@Component會自動加載一個名字叫refererFilter的過濾器,並且默認過濾路徑是/*

@WebFilter注解實現

網上太多博客是說實現是這樣的,可是怕是都沒有去正的實現,這樣是錯誤的

@Component
@WebFilter(urlPatterns = "/user/*", filterName = "ref")
public class RefererFilter implements Filter {

image
看了日志后我們發現,@WebFilter定義名字叫ref的並沒有實現,反倒是@Component和之前一樣默認創建了一個名字叫refererFilter的/*的過濾器

其實在springboot的啟動類上加上@ServletComponentScan就可以掃描到對應的@WebFilter 並且加載了

@SpringBootApplication
@ServletComponentScan
public class FilterApplication {


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM