Springboot的过滤器,在web开发中可以过滤指定的url
比如过拦截掉我们不需要的接口请求,同时也可以修改request和response内容
过滤器的应用场景:
1)过滤敏感词汇(防止sql注入)
2)设置字符编码
3)URL级别的权限访问控制
4)压缩响应信息
我们用一个demo来进行讲解,需要实现的场景:通过过滤器拦截所有web接口,除了白名单接口和内部接口无条件通过外,其余接口均需进行token校验
过滤器需要实现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() {
}
}
/**
* @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>
项目启动后,访问下面两个接口(白名单接口PK非白名单接口)
接口一:http://localhost:8080/whileTest
接口二:http://localhost:8080/no-while
接口一为白名单范畴,过滤器直接通行,返回“success”,如下图:
接口二在过滤器中需要校验token,在没有携带token的情况下,会重定向到登录页
---------发表人:梦想的边缘