SpringBoot拦截器的配置并实现用户登录校验

在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。

SpringBoot 提供了 Interceptor 拦截器机制,用于请求的预处理和后处理。在 SpringBoot 中定义一个拦截器有两种方法:第一种是实现 HandlerInterceptor 接口,或者继承实现了 HandlerInterceptor 接口的类(例如:HandlerInterceptorAdapter);第二种方法时实现 Spring 的 WebRequestInterceptor 接口,或者继承实现了 WebRequestInterceptor 接口的类。这些拦截器都是在Handler的执行周期内进行拦截操作的。

1、HandlerInterceptor接口

首先来看看 HandlerInterceptor 接口的源码:

package org.springframework.web.servlet;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
 
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
 
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
 
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

如果要实现 HandlerInterceptor 接口,就要实现其三个方法,分别是:preHandle、postHandle、afterCompletion。

(1)preHandle 方法在执行 Handler 方法之前执行。该方法返回值为 Boolean 类型,如果返回false,表示拦截请求,不在向下执行。而如果返回 true,表示放行,程序继续向下进行(如果后面没有其他 Interceptor,就会直接执行 Controller 方法)。所以,此方法可以对请求进行判断,决定程序是否继续执行,或者进行一些前置初始化操作及对请求做预处理。

(2)postHandle 方法在执行 Handler 之后,返回 ModelAndView 之前执行。由于该方法会在前端控制器(DispatcherServlet)进行返回视图渲染之前被调用,所以此方法多被用于统一处理返回的视图,例如将公用的模型数据(例如导航栏菜单)添加到视图,或者根据其他情况制定公用的视图。

(3)afterCompletion 方法在执行完Handler之后执行。由于是在 Controller 方法执行完毕后执行该方法,所以该方法适合进行统一的异常或者日志处理操作。

相关博文:

《JSP/Servlet实现简单的登录校验》

《SpringMVC使用拦截器(Interceptor)实现用户登录校验》

《SpringBoot拦截器的配置并实现用户登录校验》

2、使用拦截器实现用户登录校验

下面通过一个示例来使用拦截器完成登录控制,具体为拦截用户的请求,判断用户是否已经登录,如果用户没有登录,则跳转到 login 页面,如果用户已经登录,则放行。执行结果如下图:

登录失败,提示失败信息:

 登录成功,进入首页:

 (1)创建项目 

创建 SpringBoot 项目,项目结构如下图:

 (2)添加依赖

使用Maven添加依赖文件,在 pom.xml 文件中,添加需要的依赖:

<!-- Spring Boot 的 Web 依赖-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Thymeleaf 的依赖-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

(3)创建拦截器

创建 com.pjb.interceptor 包,创建登录拦截器(LoginInterceptor.java),并实现HandlerInterceptor接口,实现其三个方法。这里主要以preHandle方法为主。

package com.pjb.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 登录拦截器
 * @author pan_junbiao
 **/
public class LoginInterceptor implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        String uri = request.getRequestURI();

        //判断当前请求地址是否登录地址
        if(uri.contains("login") || uri.contains("toLoginPage"))
        {
            //登录请求,直接放行
            return true;
        }
        else
        {
            //判断用户是否登录
            if(request.getSession().getAttribute("userName")!=null)
            {
                //说明已经登录,放行
                return true;
            }
            else
            {
                //没有登录,重定向到登录界面
                response.sendRedirect(request.getContextPath() + "/toLoginPage");
            }
        }

        //默认拦截
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) throws Exception {
    }
}

(4)创建配置类

创建 com.pjb.config 包,并创建 WebMvcConfig 类,实现 WebMvcConfigurer 接口;重写  addViewControllers 方法和 addInterceptors 方法;使用 @Configuration 注解,标注该类为配置类。

了解WebMvcConfigurer配置接口的详解:

《SpringBoot中的WebMvcConfigurer配置接口的详解》

package com.pjb.config;

import com.pjb.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Web MVC 配置类
 * @author pan_junbiao
 **/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer
{
    /**
     * 控制器配置
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry)
    {
        registry.addViewController("/toIndexPage").setViewName("/index");
        registry.addViewController("/").setViewName("/index");
    }

    /**
     * 拦截器配置
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        //注册Interceptor拦截器
        InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
        registration.addPathPatterns("/**"); //所有路径都被拦截
        registration.excludePathPatterns( //添加不拦截路径
                "/toLoginPage", //登录页面
                "/login",       //登录请求
                "/**/*.html",   //html静态资源
                "/**/*.js",     //js静态资源
                "/**/*.css"     //css静态资源
        );
    }
}

(5)创建控制器

创建 com.pjb.controller 包,创建登录控制器(LoginController.java),编写登录与登出方法。

package com.pjb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;

/**
 * 登录控制器
 * @author pan_junbiao
 **/
@Controller
public class LoginController
{
    /**
     * 登录页面
     */
    @RequestMapping("/toLoginPage")
    public String toLoginPage()
    {
        //跳转至登录页面
        return "login.html";
    }

    /**
     * 登录
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(Model model, HttpServletRequest request, String userName, String password)
    {
        //验证登录信息
        if (userName.equals("pan_junbiao的博客") && password.equals("123456"))
        {
            //验证成功,记录Session信息
            request.getSession().setAttribute("userName", userName);

            //重定向到首页
            return "redirect:toIndexPage";
        }
        else
        {
            model.addAttribute("errorMsg", "账号或密码错误!");
        }

        //跳转至登录页面
        return toLoginPage();
    }

    /**
     * 登出
     */
    @RequestMapping(value = "/logout")
    public String logout(HttpServletRequest request)
    {
        //销毁session对象
        request.getSession().invalidate();

        //重定向到登录页面
        return "redirect:toLoginPage";
    }
}

 (6)创建视图

创建用户登录页面(Login.html)。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <meta name="author" content="pan_junbiao的博客">
    <style>
        .txtBox{
            padding: 3px;
            width: 250px;
            font-size: 16px;
        }
    </style>
</head>
<body>
<div align="center">请输入登录信息
    <form name="myForm" method="post" action="/login" onsubmit="SubmitLogin()">
        <table>
            <tr>
                <td>用户姓名:</td>
                <td><input type="text" name="userName" value="pan_junbiao的博客" class="txtBox" /></td>
            </tr>
            <tr>
                <td>登录密码:</td>
                <td><input type="password" name="password" value="123456" class="txtBox"/></td>
            </tr>
            <!-- 以下是提交、取消按钮 -->
            <tr>
                <td>
                    <input type="submit" value="登录" />
                </td>
                <td>
                    <input type="reset" value="取消" />
                </td>
            </tr>
        </table>
        <p style="color:red" th:text="${errorMsg}"></p>
    </form>
</div>
</body>
<script>
    //提交登录
    function SubmitLogin() {
        //判断用户名是否为空
        if (!myForm.userName.value) {
            alert("请输入用户姓名!");
            myForm.userName.focus();
            return false;
        }

        //判断密码是否为空
        if (!myForm.password.value) {
            alert("请输入登录密码!");
            myForm.password.focus();
            return false;
        }
        return true;
    }
</script>
</html>

创建首页(index.html)。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
    <h1>首页</h1>
    <p>当前Session中保存的登录人名称:<span th:text="${session.userName}"/></p>
    <p>您好,欢迎访问 pan_junbiao的博客!</p>
    <p>博客地址:https://blog.csdn.net/pan_junbiao</p>
    <a href="logout" onclick="return confirm('确定注销吗?');">注销</a>
</body>
</html>

  • 21
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Spring Boot拦截器是一种用于在请求到达目标方法之前或之后执行一些操作的机制。在实现登录校验时,可以使用拦截器来拦截请求,并进行登录状态的验证。 首先,需要编写一个拦截器类来实现登录校验的逻辑。拦截器类需要继承HandlerInterceptorAdapter,并重写preHandle方法。在preHandle方法中,可以获取到请求的信息,如请求路径和参数。根据业务需要,可以从请求中获取登录状态信息,进行验证。 其次,需要配置拦截器类生效的路径。在Spring Boot中,可以通过配置类或注解来配置拦截器类。可以使用@Configuration注解标注一个配置类,并通过implements WebMvcConfigurer接口来添加拦截器。 在配置类中,可以通过重写addInterceptors方法来配置拦截器。将拦截器对象添加到InterceptorRegistry中,并设置拦截的路径。可以使用addPathPatterns方法来设置拦截的路径模式,如"/user/*"表示拦截以/user/开头的路径。 在拦截器生效后,当发起请求时,拦截器会拦截请求并调用preHandle方法进行登录校验。如果登录状态验证失败,可以根据业务需要进行处理,如返回错误信息或进行重定向。 需要注意的是,拦截器拦截的是请求,而不是方法。也就是说,拦截器会在请求到达目标方法之前执行,但不会影响目标方法的执行。如果需要在拦截器中进行一些后续操作,可以使用postHandle和afterCompletion方法。 通过使用Spring Boot拦截器校验登录,可以在请求到达目标方法之前进行登录状态的验证,确保只有已登录的用户才能访问敏感接口或页面,提高系统的安全性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pan_junbiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值