zoukankan      html  css  js  c++  java
  • SpringBoot

    前言

    记录下AOP实现登录状态的检查,文章使用的JWT校验参考:SpringBoot - 集成Auth0 JWT


    实现登录状态检查的方式

    • Servlet过滤器
    • 拦截器
    • Spring AOP

    AOP 定义

    AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,在程序开发中主要用来解决一些系统层面上的问题,在不改变原有的逻辑的基础上,增加一些额外的功能,如日志,事务,权限等


    AOP 相关概念

    术语 概念 描述
    Aspect 切面 通知和切点的集合
    Joint point 连接点 应用执行过程中能够插入切面的一个点
    Advice 通知 定义切面是什么以及何时使用
    Pointcut 切点 定义切面在何处执行,切点的定义会匹配通知所有要织入的连接点
    Weaving 织入 把切面应用到目标对象并创建新的代理代理对象的过程

    Advice 通知类型

    术语 概念 描述
    Before 前置通知 在目标方法被调用之前调用通知功能
    After 后置通知 在目标方法完成之后调用,此时不关心方法的输出是什么
    AfterReturning 返回通知 在目标方法成功执行之后调用通知
    AfterThrowing 异常通知 在目标方法抛出异常后调用通知
    Around 环绕通知 通知包裹了通知的方法,在被通知的方法调用之前和调用之后执行自定义行为

    具体实现

    实现代码

    • 自定义注解CheckLogin
    /**
     * @Description 登录校验注解
     * @author coisini
     * @date Oct 14, 2021
     * @Version 1.0
     */
    public @interface CheckLogin {
    }
    
    • 切面CheckLoginAspect
    import com.coisini.aop.util.JwtUtil;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @Description 登录校验切面
     * @author coisini
     * @date Oct 14, 2021
     * @Version 1.0
     */
    @Aspect
    @Component
    public class CheckLoginAspect {
    
        /**
         * 只要加了@CheckLogin的方法都会走到这里
         * @param point
         * @return
         */
        @Around("@annotation(com.coisini.aop.auth.annotation.CheckLogin)")
        public Object checkLogin(ProceedingJoinPoint point) {
            try {
                // 从header中获取token
                RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
                ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
                HttpServletRequest request = attributes.getRequest();
    
                String token = request.getHeader("token");
    
                // 校验token是否合法
                Boolean valid = JwtUtil.verifyToken(token);
                if (!valid) {
                    throw new ServerErrorException(HttpStatus.UNAUTHORIZED.value(), "Token 不合法");
                }
    
                // 执行后续的方法
                return point.proceed();
            } catch (Throwable throwable) {
                throw new ServerErrorException(HttpStatus.UNAUTHORIZED.value(), "Token 不合法");
            }
        }
    }
    
    • 自定义异常ServerErrorException
    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    /**
     * @Description 自定义异常
     * @author coisini
     * @date Oct 14, 2021
     * @Version 1.0
     */
    @Data
    @AllArgsConstructor
    public class ServerErrorException extends RuntimeException{
    
        public Integer code;
        public String message;
    
    }
    
    • 统一异常处理GlobalExceptionAdvice
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    /**
     * @Description 统一异常处理
     * @author coisini
     * @date Oct 14, 2021
     * @Version 1.0
     */
    @RestControllerAdvice
    @Slf4j
    public class GlobalExceptionAdvice {
    
        @ExceptionHandler(ServerErrorException.class)
        public ResponseEntity<UnifyMessage> handleServerErrorException(ServerErrorException e) {
    
            log.warn("ServerErrorException 异常", e);
    
            return new ResponseEntity<>(
                    UnifyMessage.builder()
                            .code(e.getCode())
                            .message(e.getMessage())
                            .build(),
                    HttpStatus.UNAUTHORIZED
            );
        }
    
    }
    
    • 统一消息返回UnifyMessage
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @Description 统一消息返回
     * @author coisini
     * @date Oct 14, 2021
     * @Version 1.0
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public class UnifyMessage {
    
        private int code;
        private String message;
    
    }
    

    测试

    • 测试方法TestController
    /**
     * AOP校验请求头中的Token
     * @return
     */
    @CheckLogin
    @GetMapping(value = "/test")
    public String testCheckLogin() {
        // TODO 业务
        return "Token验证通过";
    }
    
    • 获取Token

    在这里插入图片描述


    • Token测试

    在这里插入图片描述


    • 传递Token

    在这里插入图片描述



    源码

    GitHubhttps://github.com/maggieq8324/java-learn-demo/tree/master/springboot-aop


    - End -
    白嫖有风险
    点赞加收藏
    以上为本篇文章的主要内容,希望大家多提意见,如果喜欢记得点个推荐哦
    作者:Maggieq8324
    本文版权归作者和博客园共有,欢迎转载,转载时保留原作者和文章地址即可。
  • 相关阅读:
    循序渐进学Python 1 安装与入门
    常用yum命令小结
    为CentOS配置网易163的yum源
    PHP合并数组+与array_merge的区别
    让Docker功能更强大的10个开源工具
    Docker入门系列8
    Docker入门系列7 动态映射端口port mapping
    e 的由来
    ROS教程5 使用串口
    1 ROS+ 使用ORB_SLAM2进行全场定位
  • 原文地址:https://www.cnblogs.com/maggieq8324/p/15406015.html
Copyright © 2011-2022 走看看