springboot自定义拦截器,拦截前端请求

教你2步完成springboot的自定义拦截器,拦截前端请求。

1、应用场景

需要对前端请求进行统一拦截,校验用户是否登录;或请求的签名合法性;主要应用到两个类:

第一个:WebMvcConfigurer,第二个:HandlerInterceptor。

2、实现

首先实现WebMvcConfigurer,重写addInterceptors()方法,我这里的SignInterceptor类是自定义的类,下面再讲。后面的/** 表示对所有请求进行拦截,可以根据自己的实际场景更改。

import com.hdx.admin.biz.annotation.LoginUserHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * 定义执行的拦截器
 * @Author 
 * @Date 
 */
@Configuration
public class AppMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SignInterceptor()).addPathPatterns("/**");
    }

}

第二步,自己定义一个要执行的类(我定义的是SignInterceptor)实现HandlerInterceptor,重写其中的perHandle()方法,这个里面就可以写自己的业务实现了。static静态块中定义了不需要进行拦截处理的接口地址。



import com.ht.publicc.common.constans.SystemConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 系统接口签名拦截
 *
 * @Author
 */
public class SignInterceptor implements HandlerInterceptor {
    Logger logger = LoggerFactory.getLogger(SignInterceptor.class);

    private static Map<String, String> filterMap = new HashMap<>();

    /**
     * 请求白名单,这里的请求接口将直接跳过该拦截器。
     * 不进行登录校验与签名校验
     */
    static {
        filterMap.put("/demoApp/login", "登录");
        filterMap.put("/demoApp/logout", "退出登录");
        filterMap.put("/demoApp/captchaImage", "验证码");

        filterMap.put("/demoAdmin/login", "登录");
        filterMap.put("/demoAdmin/logout", "退出登录");
        filterMap.put("/demoAdmin/captchaImage", "验证码");
        filterMap.put("/demoAdmin/tool/gen/batchGenCode", "验证码");

        filterMap.put("/captchaImage", "验证码");
    }

    /**
     * 重写拦截器方法
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        if (filterMap.containsKey(url)) {
            return Boolean.TRUE;
        }

        //业务实现写在这里
       
        return Boolean.TRUE;
    }

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

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

下面的是我的实现,可以参考。不可以直接使用。



import com.hdx.admin.manager.constans.SystemConfig;
import com.hdx.admin.manager.redis.RedisKeyUtil;
import com.hdx.admin.manager.redis.RedisUtil;
import com.hdx.admin.manager.system.AppContext;
import com.hdx.admin.manager.system.UserTokenManager;
import com.hdx.system.common.pojo.bo.SysUserBO;
import com.ht.publicc.common.appexception.AppErrorCodeEnum;
import com.ht.publicc.common.appexception.AppErrorMessage;
import com.ht.publicc.common.appexception.AppException;
import com.ht.publicc.common.constans.SystemConstant;
import com.ht.publicc.common.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 系统接口签名拦截
 *
 * @Author
 */
public class SignInterceptor implements HandlerInterceptor {
    Logger logger = LoggerFactory.getLogger(SignInterceptor.class);

    private static Map<String, String> filterMap = new HashMap<>();

    /**
     * 请求白名单,这里的请求接口将直接跳过该拦截器。
     * 不进行登录校验与签名校验
     */
    static {
        filterMap.put("/demoApp/login", "退出登录");
        filterMap.put("/demoApp/logout", "退出登录");
        filterMap.put("/demoApp/captchaImage", "验证码");

        filterMap.put("/demoAdmin/login", "登录");
        filterMap.put("/demoAdmin/logout", "退出登录");
        filterMap.put("/demoAdmin/captchaImage", "验证码");
        filterMap.put("/demoAdmin/tool/gen/batchGenCode", "验证码");

        filterMap.put("/captchaImage", "验证码");
    }

    /**
     * 重写拦截器方法
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        if (filterMap.containsKey(url)) {
            return Boolean.TRUE;
        }
        //签名类型的key
        String signKey = RedisKeyUtil.getFilterUrlKey(SystemConstant.STR_1, url);
        //登录类型的key
        String loginKey = RedisKeyUtil.getFilterUrlKey(SystemConstant.STR_2, url);
//        String token = request.getHeader(config.HEAD_TOKEN_NAME)

        RedisUtil redis = AppContext.getBean(RedisUtil.class);
        //是否验证签名 签名开关等于0 且 redis中没有该过滤的url,则验证签名
        if (SystemConfig.getSignSwitch() && StringUtils.isEmpty(redis.get(signKey))) {
            checkSign(request);
        }

        //是否验证登录状态 验证登录开关等于0开启 且 redis中没有该url的过滤列表,则验证登录信息
        if (SystemConfig.getLoginSwitch() && StringUtils.isEmpty(redis.get(loginKey))) {
            checkLogin(request);
        }
        return Boolean.TRUE;
    }

    private void checkSign(HttpServletRequest request) throws AppException {
        String sign = request.getHeader(SystemConstant.HEAD_SIGN).toUpperCase(Locale.ROOT);
        String timestamp = request.getHeader(SystemConstant.TIMESTAMP_NAME);
        if (StringUtils.isEmpty(sign)) {
            throw new AppException(AppErrorCodeEnum.CUSTOM_ERROR, AppErrorMessage.SIGN_ERROR);
        }
        if (StringUtils.isEmpty(timestamp)) {
            throw new AppException(AppErrorCodeEnum.CUSTOM_ERROR, AppErrorMessage.TIMESTAMP_ERROR);
        }
        StringBuffer buffer = new StringBuffer(SystemConfig.secretKey).append(timestamp);
        String sysSign = MD5Util.encryptionToMD5(buffer.toString()).toUpperCase(Locale.ROOT);
        if (!sysSign.equals(sign)) {
            logger.error("- SignInterceptor.checkSign - 签名错误,请求已被拦截 - 参数 - sign:{}, timestamp:{}, sysSign :{}", sign, timestamp, sysSign);
            throw new AppException(AppErrorCodeEnum.CUSTOM_ERROR, AppErrorMessage.SIGN_ERROR);
        }
    }

    private void checkLogin(HttpServletRequest request) throws AppException {
        String token = request.getHeader(SystemConstant.TOKEN_NAME);
        if (StringUtils.isEmpty(token)) {
            logger.error("SignInterceptor.checkLogin - 请求token为空,登录验证不通过");
            throw new AppException(AppErrorCodeEnum.UN_LOGIN);
        }
        SysUserBO userBO = UserTokenManager.getInstance().getLoginUser(token, request);
        if (userBO == null) {
            logger.error("SignInterceptor.checkLogin - 登录验证不通过 - token={}", token);
            throw new AppException(AppErrorCodeEnum.UN_LOGIN);
        }
    }

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 拦截器中可以通过返回一个自定义的响应实体对象来发送通知到前端 Vue 中。具体实现步骤如下: 1. 自定义一个响应实体类,用于封装通知信息,例如: ``` public class ResponseData { private Integer code; private String message; // 省略 getter 和 setter 方法 } ``` 2. 在拦截器中判断是否需要发送通知,并设置通知信息到响应实体类中,例如: ``` @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 判断是否需要发送通知 if (needToSendNotification(request)) { // 设置通知信息到响应实体类中 ResponseData responseData = new ResponseData(); responseData.setCode(200); responseData.setMessage("您有新的消息,请注意查收!"); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(new ObjectMapper().writeValueAsString(responseData)); return false; } return true; } ``` 3. 在 Vue 中使用 axios 发送请求,并处理响应实体类中的通知信息,例如: ``` axios.interceptors.response.use( response => { // 判断响应状态码是否为 200 if (response.status === 200) { // 解析响应实体类中的通知信息 let responseData = response.data; if (responseData.code === 200) { // 显示通知信息 alert(responseData.message); } } return response; }, error => { // 处理错误信息 console.log(error); return Promise.reject(error); } ); ``` 通过以上步骤,就可以在 Spring Boot 拦截器中发送通知到前端 Vue 中了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值