自定义拦截器(比如token校验的拦截器)

文章介绍了如何在SpringMVC环境中自定义拦截器配置类,包括设置拦截路径和放行路径,以及创建一个用于标记接口是否需要token校验的注解。通过实现HandlerInterceptor接口,具体实现了Token校验的逻辑,检查请求头中的token并进行权限验证。如果方法上有@NotCheckToken注解,则跳过校验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现步骤:

一、自定义一个拦截器配置类,里面可以配置不同的拦截器,比如校验token的、校验权限的等,在里面可以设置拦截的路径和放行的路径等。
二、自定义注解(以校验token为例子,我自定义了@NotCheckToken这个注解,当控制层使用这个注解,表示放行,该接口不进行token的校验)
三、实现具体的拦截器,比如token校验的,你校验token的逻辑要写在这个类里面,具体的处理,preHandler方法表示进行拦截,然后判断是否使用@NotCheckToken注解, 没有使用这个注解则需要进行token校验。

具体实现

1、InterceptorConfig(拦截器配置类)

package com.lancoo.primaryedu.Interceptor;

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

/**
 * @description: 自定义拦截器
 * @author: daiziru
 * @date: 2023/7/14 15:39
 * @param:
 * @return:
 **/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    /**
     * 配置拦截路径
     *
     * @param registry 拦截器参考
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // token 拦截所有请求,通过判断是否有 @NotCheckToken 注解 决定是否需要校验
        registry
                .addInterceptor(tokenInterceptor()) //添加需要的自定义拦截器
                .addPathPatterns("/**"); //对所有路径进行拦截
    }

    /**
     * token 拦截器注入
     *
     * @return Token 拦截器
     */
    @Bean
    public TokenInterceptor tokenInterceptor() {
        return new TokenInterceptor();
    }

}

2、自定义注解NotCheckToken

package com.lancoo.primaryedu.Interceptor;

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

/**
 * 自定义 Token 校验注解
 * @author pky
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotCheckToken {
    boolean required() default true;
}

3、token具体的拦截器

package com.lancoo.primaryedu.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.lancoo.common.exception.MyException;
import com.lancoo.common.respone.StatusCode;
import com.lancoo.common.utils.JsonUtil;
import com.lancoo.primaryedu.entity.net.BasePlatOutBean;
import com.lancoo.primaryedu.entity.net.NetUtil;
import com.lancoo.primaryedu.entity.net.OutCome;
import com.lancoo.primaryedu.entity.net.RequestResponse;
import com.lancoo.primaryedu.util.CommonUtil;
import com.lancoo.primaryedu.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Token 拦截器
 * @author pky
 */
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private Environment environment;


    /**
     * @description: 通过检查是否有@NotCheckToken注解,决定是否进行token校验
     * @author: daiziru
     * @date: 2023/7/14 15:31
     * @param: [request, response, object]
     * @return: boolean
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        // 从 http 请求头中取出 token
        String token = CommonUtil.handleHeader(request).getToken();
        if(null == token || "".equals(token)) {
            throw new MyException(StatusCode.REMIND, "请求头中不存在token或token不正确!");
        }
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
//         检查用户权限的注解
        if (method.isAnnotationPresent(NotCheckToken.class)) {
            NotCheckToken notCheckToken = method.getAnnotation(NotCheckToken.class);
            if (notCheckToken.required()) {
                return true;
            }
        }
        return checkToken(request, token);
    }

    /**
     * 校验 token
     *
     * @param request 请求
     * @param token   令牌
     * @return 校验结果,true/通过;false/不通过
     * @throws Exception 可能出现的异常
     */
    private boolean checkToken(HttpServletRequest request, String token) throws Exception {
        if (null == token) {
            token = "";
        }
        String ADDR = "/UserMgr/Login/Api/Login.ashx";
        String yunAddr = environment.getProperty("base.addr");
        String SysID = environment.getProperty("sys.id");
        Map<String, String> form = new HashMap<>();
        form.put("method", "TokenCheck");
        form.put("token", token);
        form.put("params", SysID + "|");
        String result = "";
        RequestResponse response = NetUtil.postForm(checkBaseUr(yunAddr) + ADDR, form);
        OutCome<BasePlatOutBean<BasePlatOutBean.BasePlatLoginOutDataBean>> outCome = new OutCome<>();
        if (response.isSuccessful) {
            if (!StringUtil.isEmpty(response.Data)) {
                result = response.Data;
            }
        }

        if (!result.equals("")) {
            //解析下json字符串
            Map<String, String> keyValue = new JsonUtil().getKeyValue(result);
            String re = keyValue.get("result");
            if (re == null) {
                return false;
            }
            if (re.equals("true")) {
                return true;
            }
        }
        return false;
    }

    public String checkBaseUr(String url) {
        if (url.endsWith("/")) {
            return url;
        }
        return url + "/";
    }

}
前端与Spring Boot拦截器进行Token校验的基本思路是:前端将用户登录时获取到的Token放在请求的Header中,Spring Boot拦截器通过拦截请求获取Header中的Token,然后根据Token进行校验。 下面是具体的步骤: 1. 前端在用户登录成功后,将Token保存在浏览器的本地存储(localStorage或sessionStorage)中,并在每次请求时将Token放在请求的Header中。例如: ``` axios.defaults.headers.common['Authorization'] = 'Bearer ' + token; ``` 2. Spring Boot拦截器通过实现HandlerInterceptor接口来拦截请求,并在拦截器中获取Header中的Token。例如: ``` public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); // 根据Token进行校验 if (token == null || !token.startsWith("Bearer ")) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } // ... return true; } // ... } ``` 3. 在Spring Boot的配置类中配置拦截器,使其生效。例如: ``` @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private TokenInterceptor tokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") .excludePathPatterns("/login"); } // ... } ``` 在上面的代码中,我们将TokenInterceptor添加到拦截器链中,并设置了拦截所有请求(除了/login)。 这样,当前端发送请求时,拦截器会拦截请求并获取Header中的Token,然后进行校验,如果校验不通过则返回401状态码,否则继续执行请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值