SpringBoot登录验证token拦截器的实现

目录
  • 注解定义
  • token生成与验证
  • 拦截器定义
    • 拦截器配置定义
    • 拦截器的方法执行类
    • 注解使用
  • 返回值-全局异常类定义
  • 各种测试
    • 不传token
    • 制造可行的假token
    • 伪造token测试
  • 拓展:从请求中获取token
  • 参考文章:

用户访问接口验证,如果用户没有登录,则不让他访问除登录外的任何接口。

实现思路:

1.前端登录,后端创建token(通过JWT这个依赖),返给前端

2.前端访问其他接口,传递token,后端判断token存在以或失效

3.失效或不存在,则返回失效提示,前端根据接口返回的失效提示,让其跳转到登录界面

注解定义

定义2个注解,1个用于任何接口都能访问,另外一个用于需要登录才能访问

调用都通过注解

package com.example.etf.story.tools;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean required() default true;
}

登录才能通过

package com.example.etf.story.tools;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required() default true;
}

注解的作用说明

@Target代表此注解,能@到哪些代码上

@Target:注解的作用目标

  • @Target(ElementType.TYPE)——接口、类、枚举、注解
  • @Target(ElementType.FIELD)——字段、枚举的常量
  • @Target(ElementType.METHOD)——方法
  • @Target(ElementType.PARAMETER)——方法参数
  • @Target(ElementType.CONSTRUCTOR) ——构造函数
  • @Target(ElementType.LOCAL_VARIABLE)——局部变量
  • @Target(ElementType.ANNOTATION_TYPE)——注解
  • @Target(ElementType.PACKAGE)——包

@Retention:注解的保留位置

  • RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
  • RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
  • RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
  • @Document:说明该注解将被包含在javadoc
  • @Inherited:说明子类可以继承父类中的该注解

token生成与验证

传送门

然后springBoot拦截器验证token

拦截器定义

拦截器配置定义

拦截器拦截,除了登录和发送短信,不拦截,其他都拦截

package com.example.etf.story.tools;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Resource
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自己的拦截器,并设置拦截的请求路径
        //addPathPatterns为拦截此请求路径的请求
        //excludePathPatterns为不拦截此路径的请求
        registry.addInterceptor(loginInterceptor).addPathPatterns("/story/*").excludePathPatterns("/story/sendSMS")
                .excludePathPatterns("/story/signOrRegister");
    }
}

拦截的时候,调用的方法,给谁通过

其中service查询数据库,有没有用户,的方法要自己写

拦截器的方法执行类

package com.example.etf.story.tools;

import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;

import com.example.etf.story.dao.R;
import com.example.etf.story.paramer.UserInfoParam;
import com.example.etf.story.service.TestClientService;
import com.example.etf.story.service.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Slf4j
@Component
public class LoginInterceptor extends R implements HandlerInterceptor {
    /**
     * 目标方法执行前
     * 该方法在控制器处理请求方法前执行,其返回值表示是否中断后续操作
     * 返回 true 表示继续向下执行,返回 false 表示中断后续操作
     *
     * @return
     */
    @Resource
    private TestClientService testClientService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        //检查方法是否有passtoken注解,有则跳过认证,直接通过
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new RuntimeException("无token,请重新登录");
                }
                // 获取 token 中的 user id
                String phone;
                try {
                    phone = JWT.decode(token).getClaim("phone").asString();
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("token不正确,请不要通过非法手段创建token");
                }
                //查询数据库,看看是否存在此用户,方法要自己写
                UserInfoParam userInfoParam = testClientService.selectUserByPhone(phone);
                if (userInfoParam == null) {
                    throw new RuntimeException("用户不存在,请重新登录");
                }

                // 验证 token
                if (TokenUtils.verify(token)) {
                    return true;
                } else {
                    throw new RuntimeException("token过期或不正确,请重新登录");
                }

            }
        }
          throw new RuntimeException("没有权限注解一律不通过");
    }

        /**
         * 目标方法执行后
         * 该方法在控制器处理请求方法调用之后、解析视图之前执行
         * 可以通过此方法对请求域中的模型和视图做进一步修改
         */
        @Override
        public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
        modelAndView) throws Exception {
            System.out.println("postHandle执行{}");

        }
        /**
         * 页面渲染后
         * 该方法在视图渲染结束后执行
         * 可以通过此方法实现资源清理、记录日志信息等工作
         */
        @Override
        public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception
        ex) throws Exception {
            System.out.println("afterCompletion执行异常");

        }

}

注解使用

在controller层加入注解进行测试

返回值-全局异常类定义

加入全局,异常类,这样当异常,会返回你所指定的异常

package com.example.etf.story.tools;

import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GloablExceptionHandler {
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
        String msg = e.getMessage();
        if (msg == null || msg.equals("")) {
            msg = "服务器出错";
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", msg);
        jsonObject.put("status",500)
        return jsonObject;
    }
}

各种测试

不传token

成功

制造可行的假token

我们测试一下加token后的

因为数据库里,我没有插入,所以不存在,我们在随便写个token

伪造token测试

我们在试试

程序员使用:方法不加注解,测试

程序员使用:加上,调用通过,注解

我们试试,加上通过注解

拓展:从请求中获取token

我们在试试从中获取token

参考文章:

SpringBoot集成JWT实现token验证 - 简书

springboot对请求的接口实现token拦截以及参数校验_kotomeli的博客-CSDN博客_springboot拦截请求参数

到此这篇关于SpringBoot登录验证token拦截器的实现的文章就介绍到这了,更多相关SpringBoot token拦截器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot下token短信验证登入登出权限操作(token存放redis,ali短信接口)

    SpringBoot下token短信验证登入登出(token存放redis) 不对SpringBoot进行介绍,具体的可以参考官方文档 介绍:token基本使用,redis基本使用 思路:获取短信(验证并限制发送次数,将code存放redis)-->登入(验证并限制错误次数,将用户信息及权限放token,token放redis)-->查询操作(略),主要将前两点,不足的希望指出,谢谢 步骤: 1.整合Redis需要的依赖,yml自行配置,ali短信接口依赖(使用引入外部包的方式) <de

  • SpringBoot整合JWT框架,解决Token跨域验证问题

    一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3.服务器向返回sessionId,写入客户端 Cookie. 4.客户端每次请求,需要通过 Cookie,将 sessionId 回传服务器. 5.服务器收到 sessionId,验证客户端. 2.存在问题 1.session保存在服务端,客户端访问高并发时,服务端压力大. 2.扩展性差,服务器集群,就需要 session 数据共享. 二.JWT简介 JWT

  • 实战SpringBoot集成JWT实现token验证

    目录 环境搭建 1.新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包 2.数据库结构 3.配置文件application.properties 4.Entity包下新建一个User类 5.Dao包下新建一个UserDao 6.Service包下新建一个USerService 7.UseService的实现类UserServiceImp 8.controller包下新建一个UserController 9.在resource文件夹下新建一个Usermapper文件

  • Springboot 如何实现filter拦截token验证和跨域

    Springboot filter拦截token验证和跨域 背景 web验证授权合法的一般分为下面几种 使用session作为验证合法用户访问的验证方式 使用自己实现的token 使用OCA标准 在使用API接口授权验证时,token是自定义的方式实现起来不需要引入其他东西,关键是简单实用. 合法登陆后一般使用用户UID+盐值+时间戳使用多层对称加密生成token并放入分布式缓存中设置固定的过期时间长(和session的方式有些相同),这样当用户访问时使用token可以解密获取它的UID并据此验

  • SpringBoot集成JWT实现token验证的流程

    JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息.因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名. JWT请求流程 1. 用户使

  • SpringBoot登录验证token拦截器的实现

    目录 注解定义 token生成与验证 拦截器定义 拦截器配置定义 拦截器的方法执行类 注解使用 返回值-全局异常类定义 各种测试 不传token 制造可行的假token 伪造token测试 拓展:从请求中获取token 参考文章: 用户访问接口验证,如果用户没有登录,则不让他访问除登录外的任何接口. 实现思路: 1.前端登录,后端创建token(通过JWT这个依赖),返给前端 2.前端访问其他接口,传递token,后端判断token存在以或失效 3.失效或不存在,则返回失效提示,前端根据接口返回

  • SpringBoot登录用户权限拦截器

    1. 创建自定义拦截器类并实现 HandlerInterceptor 接口 package com.xgf.online_mall.interceptor; import com.xgf.online_mall.system.domain.User; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.servlet.Ha

  • 在SpringBoot项目中整合拦截器的详细步骤

    目录 引言 1.创建一个SpringBoot项目工程 2.配置自定义的拦截器 3.注册拦截器 4.编写控制器 总结 引言 拦截器在Web系统中非常常见,对于某些全局统一的操作,我们可以把它提取到拦截器中实现.总结起来,拦截器大致有以下几种使用场景: 1.权限检查:如登录检测,进入处理程序检测用户是否登录,如果没有,则直接返回登录页面或error错误页面: 2.性能检测:有时系统在某段时间莫名其妙很慢,我们可以通过拦截器在进入处理程序之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时

  • springboot整合mybatis分页拦截器的问题小结

    简介 又到了吹水时间,是这样的,今天开发时想将自己写好的代码拿来优化,因为不想在开发服弄,怕搞坏了到时候GIT到生产服一大堆问题,然后把它分离到我轮子(工具)项目上,最后运行后发现我获取List的时候很卡至少10秒,我惊了平时也就我的正常版本是800ms左右(不要看它很久,因为数据量很大,也很正常.),前提是我也知道很慢,就等的确需要优化时,我在放出我优化的plus版本,回到10秒哪里,最开始我刚刚接到这个app项目时,在我用 PageHelper.startPage(page, num);(分

  • SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

    目录 SpringBoot整合Mybatis自定义拦截器不起作用 1. 原始的读取mybatis-config.xml文件 2. 与SpringBoot容器整合 2.1 mybatis的自动装载 3. 在mybatis-config.xml配置又放入Spring容器 SpringBoot 自定义Mybatis拦截器 第一种 第二种 第三种 SpringBoot整合Mybatis自定义拦截器不起作用 Mybatis插件生效的方式: 1. 原始的读取mybatis-config.xml文件 该方式和

  • SpringBoot使用过滤器、拦截器和监听器的案例代码(Springboot搭建java项目)

    目录 SpringBoot使用过滤器.拦截器和监听器 一.SpringBoot使用过滤器 Spring boot过滤器的使用(两种方式) 方式一: 方式二: 二.SpringBoot使用拦截器 三.过滤器和拦截器的执行顺序 四.SpringBoot使用监听器 1.统计网站最多在线人数监听器的例子 2.springboot监听器的使用(以实现异步Event监听为例子) SpringBoot使用过滤器.拦截器和监听器 一.SpringBoot使用过滤器 Spring boot过滤器的使用(两种方式)

  • SpringBoot实现过滤器、拦截器与切片的实现和区别

    Q:使用过滤器.拦截器与切片实现每个请求耗时的统计,并比较三者的区别与联系 过滤器Filter 过滤器概念 Filter是J2E中来的,可以看做是 Servlet 的一种"加强版",它主要用于对用户请求进行预处理和后处理,拥有一个典型的 处理链 .Filter也可以对用户请求生成响应,这一点与Servlet相同,但实际上很少会使用Filter向用户请求生成响应.使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行预处理并生成响应,最后Filt

  • Spring mvc 实现用户登录的方法(拦截器)

    用户登录时,将用户信息放到session中 package cn.woniubushiniu.controller; import cn.woniubushiniu.po.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import o

  • SpringBoot配置拦截器实现过程详解

    目录 如何配置拦截器 拦截器设置容易出现的问题 如何取消拦截操作 实例-登录验证 如何配置拦截器 step1: 自定义拦截器 /** * 自定义拦截器 */ public class MyInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(MyInterceptor.class); /** * 在请求匹配controller之前执行,返回t

  • SpringBoot快速设置拦截器并实现权限验证的方法

    一.概述 拦截器的使用场景越来越多,尤其是面向切片编程流行之后.那通常拦截器可以做什么呢? 之前我们在Agent介绍中,提到过统计函数的调用耗时.这个思路其实和AOP的环绕增强如出一辙. 那一般来说,场景如下: 函数增强:比如对一个函数进行参数检查,或者结果过滤等.甚至可以对函数就行权限认证. 性能监控:统计函数性能. 日志打点:比如在用户登录函数之前,打点统计PV等信息. 以及其他等等. 二.Spring的拦截器 无论是SpringMVC或者SpringBoot中,关于拦截器不得不提: org

随机推荐