Springboot——过滤器

Springboot的过滤器,在web开发中可以过滤指定的url
比如过拦截掉我们不需要的接口请求,同时也可以修改request和response内容
过滤器的应用场景:
1)过滤敏感词汇(防止sql注入)
2)设置字符编码
3)URL级别的权限访问控制
4)压缩响应信息

我们用一个demo来进行讲解,需要实现的场景:通过过滤器拦截所有web接口,除了白名单接口和内部接口无条件通过外,其余接口均需进行token校验

1.自定义过滤器

过滤器需要实现Filter类,其中有三个默认的方法(init初始方法,doFilter核心过滤方法,destroy销毁方法)

/**
 * @description:
 * @author: 梦想的边缘
 * @create: 2021/08/11 10:44
 */
public class BaseFilter implements Filter {
    Logger logger = LoggerFactory.getLogger(BaseFilter.class);

    static final String TOKEN = "20220423344556abac";
    
    //内部接口集合
    public static List<String> INSIDE_URLS = Lists.newArrayList("/index","/inside");
    //白名单接口集合
    public static List<String> WHITE_PATH = Lists.newArrayList("/white","/login");


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("初始化数据");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse)servletResponse);
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestURI = request.getRequestURI();
        if(INSIDE_URLS.contains(requestURI)){
            //内部接口,直接通过
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        if(WHITE_PATH.contains(requestURI)){
            //白名单接口,直接通过
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //进行校验,如token校验
        String token = request.getHeader("token");
        if(TOKEN.equals(token)){
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            //token校验不通过,重定向到登录页面
            wrapper.sendRedirect("/login");
        }

    }

    @Override
    public void destroy() {
    }
}

2.过滤器配置类


/**
 * @description:
 * @author: 梦想的边缘
 * @create: 2021/08/11 10:39
 */
@Configuration
public class FilterConfig {
    /**
     * 基础过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean<Filter> baseFilter(){
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new BaseFilter());
        filterRegistrationBean.setUrlPatterns(Lists.newArrayList("/*"));
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}

为了配合测试,我们新增controller方法和登录页login.html
接口:

/**
 * @description:
 * @author: 梦想的边缘
 * @create: 2021/08/01 23:37
 */
@RestController
public class restController {

    @Autowired
    private AsynService asynService;
    /**
     * 白名单接口
     * @return
     */
    @GetMapping("/while")
    public String whileTest(){
        return "success";
    }

    /**
     * 非白名单接口
     * @return
     */
    @GetMapping("/no-while")
    public String noWhileTest(){
        return "success";
    }

    /**
     * 登录接口
     * @param username
     * @param password
     * @param mv
     * @param request
     * @param model
     * @return
     */
    @GetMapping("/login")
    public ModelAndView login(String username, String password, ModelAndView mv, HttpServletRequest request, Model model){
        if(StringUtils.hasLength(username)&&StringUtils.hasLength(password)){
            //TODO 登录逻辑
            System.out.println("成功!!");
            mv.setViewName("index");
        }else{
            System.out.println("失败!!");
            mv.setViewName("/login.html");
        }
        return mv;
    }
}

login.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>登录测试页面</title>
    <link rel="stylesheet" href="css/style.css"/>
    <style>
        #parent{
            width:500px;
            height:200px;
            margin-top:20%;
            margin-left:50%;
            transform:translate(-50%,-50%) ;
            background:#009688;
        }
        .password,.subBtn{
            margin-top: 2%;
            margin-left: 3%;
        }
        .loginHeader{
            padding-top: 1%;
        }
    </style>
</head>
<body class="login_bg">
<div id="parent">
    <section class="loginBox">
        <header class="loginHeader" style="text-align:center; ">
            <h1>登录测试页面</h1>
        </header>
        <section class="loginCont">
            <form class="loginForm" action="/user/login" method="post" onsubmit="return check()" >
                <div class="inputbox"  style="text-align:center; ">
                    <label for="user">用户名:</label>
                    <input id="user" type="text" name="userName" placeholder="请输入用户名" required="required" />
                </div>
                <div class="password"  style="text-align:center; " >
                    <label for="mima">密码:</label>
                    <input id="mima" type="password" name="password" placeholder="请输入密码" required="required" />
                </div>
                <div class="subBtn"  style="text-align:center; ">
                    <input type="submit" value="登录" />
                    <input type="reset" value="重置"/>
                </div>
            </form>
        </section>
    </section>
</div>
</body>
</html>

3.测试

项目启动后,访问下面两个接口(白名单接口PK非白名单接口)
接口一:http://localhost:8080/whileTest
接口二:http://localhost:8080/no-while

接口一为白名单范畴,过滤器直接通行,返回“success”,如下图:
在这里插入图片描述

接口二在过滤器中需要校验token,在没有携带token的情况下,会重定向到登录页

---------发表人:梦想的边缘

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐