Spring AOP【用户登陆统一验证功能】

简介: Spring AOP【用户登陆统一验证功能】

🍎一. 用户登陆统一验证功能

🍒1.1 用户登录验证的几种方法


  1. 第一版的用户登陆验证: 在每个方法里获取 session 和 session 中的用户信息,如果用户存在,那么就认为登陆成功了,否则就失败了


  1. 第二版的用户登陆验证: 提供统一的方法,在每个需要验证用户登陆的方法调用统一验证用户登陆的方法来进行判断


  1. 第二版的用户登陆验证: 使用Spring AOP 来使用统一的用户登陆检验

    遇到的问题:

● 没有办法获取到HttpSession 和 Request 对象

● 实际拦截规则很复杂,使用简单的 aspect j 表达式无法满足拦截的需求


 4.第二版的用户登陆验证: Spring 拦截器来实现用户的统一登陆验证功能


● 实现自定义拦截器 添加@Component注解,实现 Spring为我们提供的 HandlerInterceptor 接口中的 重写preHandler 方法

(一个项目中可以配置多个拦截器).

● 将自定义拦截器加入到框架的配置中去, 并且设置拦截规则如下:

(1) 给要将拦截器加入到的当前类中 叫@Configuration注解

(2) 实现 WebMvcConfigurer接口

(3) 重写 addInterceptors方法来实现需要拦截的页面,和不需要拦截的页面(白名单)


这里我们看到之前的代码里过于耦合,并且繁琐,接下来我们来学习Spring’为我们提供的框架

@RestController
@RequestMapping("/user")
public class UserController {
  /**
   * 某⽅法 1
   */
  @RequestMapping("/m1")
  public Object method(HttpServletRequest request) {
    // 有 session 就获取,没有不会创建
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute("userinfo") != null) {
      // 说明已经登录,业务处理
      return true;
    } else {
      // 未登录
      return false;
    }
  }
  /**
   * 某⽅法 2
   */
  @RequestMapping("/m2")
  public Object method2(HttpServletRequest request) {
    // 有 session 就获取,没有不会创建
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute("userinfo") != null) {
      // 说明已经登录,业务处理
      return true;
    } else {
      // 未登录
      return false;
    }
  }
  // 其他⽅法...
}

🍒1.2 创建前端页面

登陆页面:


<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>登录页面</h1>
</body>
</html>

欢迎页面:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1> index 页面</h1>
</body>
</html>

🍒1.3 创建登陆方法和欢迎进入方法


package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RequestMapping("/user")
@RestController
public class UserController {
   // 登陆页面
    @RequestMapping("/login")
    public boolean login(HttpServletRequest request,String username, String password){
        boolean result = false;
        // 判断是否在登陆页面输入账号 和 密码
        if (StringUtils.hasLength(username) && StringUtils.hasLength(password)){
            // 验证输入的账号 和 密码 是否正确
            if (username.equals("admin") && password.equals("admin")){
                // 判断输入的账号和密码正确后 建立一个 session对象进行存储
                HttpSession session = request.getSession();
                session.setAttribute("userinfo","userinfo");
                return  true;
            }
        }
        return  result;
    }
    // 欢迎页面
    @RequestMapping("/index")
    public String index() {
          return "Hello,Index";
    }


🍒1.4 自定义一个拦截器


对于以上问题 Spring 中提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步

骤:


  1. 创建⾃定义拦截器,实现 HandlerInterceptor 接⼝的 preHandle(执⾏具体⽅法之前的预处理)⽅法
  2. 将⾃定义拦截器加⼊实现接口 WebMvcConfigurer 类的,重写 addInterceptors ⽅法中
    具体实现如下:


一.创建⾃定义拦截器:


package com.example.demo.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 *  自定义登陆用户登陆拦截器
 */
@Component
public class LoginIntercept implements HandlerInterceptor {
    /**
     * 返回 ture 表示拦截判断通过, 可以访问后面的接口, 如果返回false 表示拦截未通过,直接返回结果给前端
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     HttpSession session =  request.getSession(false);
     if (session != null && session.getAttribute("userinfo") != null ){
         // 表示已经登陆
         return true;
     }
     // 使用重定向方法 将表示未登录,就可以使用户跳转登陆页面
        response.sendRedirect("/login.html");
     return  false;
    }
}

二.将自定义拦截器加入到框架的配置中去


package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
//配置存储
@Configuration
public class AppConfig implements WebMvcConfigurer {
    // 通过属性注入到拦截器
    // 通过注入拦截器来配置规则
    @Autowired
    private LoginIntercept loginIntercept;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //通过registry.addInterceptor可以得到拦截器
        // 登陆拦截 需要 通过属性注入来获取有loginIntercept拦截器对象执行拦截方法
           // addPathPatterns 是拦截方法
           // excludePathPatterns 不拦截方法是
        registry.addInterceptor(loginIntercept)
                .addPathPatterns("/**") //拦截所有 的url
                .excludePathPatterns("/user/login") //不拦截登陆
                .excludePathPatterns("/user/reg")   //不拦截注册页面
                .excludePathPatterns("/login.html") //不拦截登陆
                .excludePathPatterns("/reg.html")   //不拦截注册页面
                .excludePathPatterns("/**/*.js")    //所有的js都不拦截
                .excludePathPatterns("/**/*.css")   //所有的css都不拦截
                .excludePathPatterns("/**/*.png");  //所有的png照片都不拦截
    }
    // 给所有请求地址添加 访问页面 带有api 前缀
//    @Override
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        configurer.addPathPrefix("api",c -> true);
//    }
}


🍒1.5 验证拦截功能

🍉1.5.1 当没有进行登陆,进入欢迎页面

当我们在没有进行登陆时,直接输入欢迎页面时


4256ddf0faac417b98d6964bfe85ecbe.png

我们通过重定向的方法就可以将用户引导到登陆页面中


7300dafaee5f45c0a700b1c5793dd8a0.png


🍉1.5.2 当用户未成功输入正确用户名和密码

我们会返回一个 false结果来提醒用户输入的用户名和密码错误


01406f45441a4404a86f945ac795e5f1.png

🍉1.5.3 当用户成功输入正确用户名和密码后登陆欢迎页面

我们先进行用户登陆成功操作


4d47469e479c4f7a8ad097cfb3055811.png


再次输入欢迎页面,我们就可以看到欢迎页面的内容啦!


32246df4daef4d39a19feb1ae363d83b.png


🍉1.5.4 使用前缀方法进行登陆

上文我们可以使用

    // 给所有请求地址添加 访问页面 带有api 前缀
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("api",c -> true);
    }

d4fe32aeda3a497e96c7da7d51b8ca92.png


5c98d5733fdb4503afeed649e2904298.png


🍒1.6 小结


通过上⾯的源码分析,我们可以看出,Spring 中的拦截器也是通过动态代理和环绕通知的思想实现的,⼤体的调⽤流程如下:



6c818188604749c2b5a0daac02edebb6.png



a452ec9ed0494244976724ab4703b5b6.jpg


相关文章
|
12天前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
25 3
|
1月前
|
JSON 安全 算法
|
12天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
32 0
|
1月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
38 0
|
26天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
97 62
|
16天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
40 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
22天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
30 1
|
24天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
44 2
|
18天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
31 0
下一篇
无影云桌面