springboot 拦截器

  • Post author:
  • Post category:其他


拦截器在项目中经常用到,可以用来拦截一些非法 Action 请求或是对 Action 请求进行一些预处理或后处理等,使得业务更符合实际需求,也可以在一定程度上保证系统的安全性。

下面以登录功能为例,演示拦截器的基本用法


登录页绑定登录地址

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="favicon.ico">

    <title>Signin Template</title>

    <!-- Bootstrap core CSS -->
    <link href="dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="css/signin.css" rel="stylesheet">
  </head>

  <body class="text-center">
    <form class="form-signin" th:action="@{/login}" method="post">
      <img class="mb-4" src="dist/brand/bootstrap-solid.svg" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.top}">Please sign in</h1>
      <p style="color:red;"  th:text="${failMsg}" th:if="${not #strings.isEmpty(failMsg)}"></p>
      <label class="sr-only" th:text="#{login.username}">Username</label>
      <input type="text" name="username" id="inputEmail" class="form-control" th:placeholder="#{login.username}" placeholder="Username" required autofocus>
      <label for="inputPassword" class="sr-only" th:text="#{login.password}">Password</label>
      <input type="password" name="password" id="inputPassword" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required>
      <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me"> [[#{login.remember}]]
        </label>
      </div>
      <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
      <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
      <a class="btn btn-sm" th:href="@{/index.html(lan='zh_CN')}">中文</a>
      <a class="btn btn-sm" th:href="@{/index.html(lan='en_US')}">English</a>
    </form>
  </body>
</html>


controller 层

为了防止重复提交,用了转发请求,并且做了视图映射

	@PostMapping(value="/login")
	public String login(@RequestParam("username") String username, 
						@RequestParam("password") String password,
						Map<String, Object>map, HttpSession session) {
		if(!StringUtils.isEmpty(username) && "xiao".equals(password)) {
			session.setAttribute("username", username);
			// 防止表单重复提交,重定向
			return "redirect:/home.html";
		}else {
			map.put("failMsg", "用户名密码错误");
			return "index";
		}
	}

视图映射,把 /home.html 请求映射到 dashboard 页面

另外,在 springboot2.1.4 的 WebMvcConfigurationSupport 中,会拦截静态资源,所以要有放行静态资源的操作。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.xiao.component.DefineLocalResolver;
import com.xiao.component.LoginInterceptor;

@Configuration
public class MyConfig extends WebMvcConfigurationSupport {

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    	// 绑定静态资源
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/","classpath:/public/");
        super.addResourceHandlers(registry);
    }

	@Override
    public void addViewControllers(ViewControllerRegistry registry) { // 请求映射
		// 浏览器发送 /pass 请求,来到 success 页面
    	registry.addViewController("/pass").setViewName("success");
    	
    	registry.addViewController("/home.html").setViewName("dashboard");
    }

	@Bean
	public LocaleResolver localeResolver() { // 注入自定义组件
		return new DefineLocalResolver();
	}
	
	@Override
	protected void addInterceptors(InterceptorRegistry registry) {  // 添加拦截器
		// 定义要拦截和放行的请求、资源
		registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/index","/css/**","/dist/**");
		super.addInterceptors(registry);
    }
 	
}

定义一个登录页面的拦截器,上面的配置类已经添加到容器中了。

HandlerInterceptor 接口的方法都是 default 类型的,是默认实现的方法,(java8 开始的新特性)需要实现的方法可以自己去接口中找。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 登录检查
 * @author Xiaogf
 */
public class LoginInterceptor implements HandlerInterceptor{
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		Object username = request.getSession().getAttribute("username");
		if(username == null) {
			//未登录,转发到登录页
			request.setAttribute("failMsg", "未登录或登录过时,请登录");
			request.getRequestDispatcher("/index").forward(request, response);
			return false;
		}else {
			return true;
		}
	}

}

以上就实现了登录功能的请求拦截。

直接输入 /home.html 请求是不能访问主页的,未登录就不能访问主页。

在这里插入图片描述

输入用户名和正确的密码后,登录就可以访问主页了

在这里插入图片描述



版权声明:本文为Alias_fa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。