SpringBoot自定义注解实现MVC层拦截验证

本文介绍了如何使用Spring MVC的HandlerInterceptor接口实现两种拦截器:AdvertiserAuthInterceptor和AuthInterceptor,用于处理不同的权限验证。这两个拦截器分别针对@AdvertiserAuthRequired和@AuthRequired注解的方法进行拦截,进行用户身份验证、权限检查和响应处理。在实际应用中,拦截器在控制器执行前后进行预处理和后处理操作,确保请求的安全性和合规性。

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

HandlerInterceptor 拦截器有三个方法:preHandle、postHandle、afterCompletion。
package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;

    void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
  1. preHandle:处理器的预处理,返回true表示流程继续,或者返回结果或者移交给下一个拦截器;返回false表示不会继续处理(流程中断),而是直接response。不会继续调用postHandle和afterCompletion方法。
  2. postHandle:后处理回调方法,发生在视图渲染之前。参数ModelAndView可以为空,不为空时会对数据进行处理或者视图渲染。
  3. afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调。
HandlerInterceptor实现类的执行过程

preHandler() -> Controller -> postHandler() -> model渲染-> afterCompletion()

实战

AdvertiserAuthInterceptor 拦截器,拦截注解@AdvertiserAuthRequired

@Slf4j
@Component
public class AdvertiserAuthInterceptor implements HandlerInterceptor
{
    @Resource
    private TokenService tokenService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        boolean assignableFrom = handler.getClass().isAssignableFrom(HandlerMethod.class);
        log.debug("apply auth interceptor in method", handler.getClass().toString());
        if (assignableFrom) {
            AdvertiserAuthRequired auth = ((HandlerMethod) handler).getMethodAnnotation(AdvertiserAuthRequired.class);
            if (auth == null) {
                log.info("The method is not intercepted by AdvertiserRequired");
                return true;
            } else {
                try {
                    String method = request.getMethod();
                    String channel = "";
                    String advertiserId = "";
                    if (method.equals(HttpMethod.GET.toString()))
                    {
                        channel =  request.getParameter("channel");
                        advertiserId = request.getParameter("advertiser_id");
                    }
                    else if (method.equals(HttpMethod.POST.toString()) || method.equals(HttpMethod.PUT.toString()))
                    {
                        BodyCachingRequestWrapper wrapper = (BodyCachingRequestWrapper) request;
                        String body = wrapper.getBody();
                        JsonElement element = JsonParser.parseString(body);
                        JsonObject object = element.getAsJsonObject();
                        channel = object.get("channel").getAsString();
                        advertiserId = object.get("advertiser_id").getAsString();
                    }

                    if (!StringUtils.hasLength(advertiserId) || !StringUtils.hasLength(channel))
                    {
                        log.info("Required advertiser_id and channel missing");
                        EbAuthUtil.setFailResponse(response, EbErrorCode.AD_INPUT_MISSING);
                        return false;
                    }

                    EbUser subject = EbAuthUtil.getSubject(request);
                    String accessToken = tokenService.retrieveAccessToken(subject, advertiserId, AdChannel.valueOf(channel));
                    return EbAuthUtil.setRequestHeader(request, response, EbConstants.EB_AK, accessToken);
                }
                catch (EbException ex)
                {
                    log.info("Couldn't find advertiserId and channel info in request body");

                    return EbAuthUtil.setFailResponse(response, ex.getErrorCode(), ex.getMsg(), ex.getDetail());
                }
                catch (RuntimeException ex)
                {
                    log.info("Failed to retrieve active accessToken");
                    return EbAuthUtil.setFailResponse(response, EbErrorCode.UNKNOWN_ERROR.getErrorCode(), EbErrorCode.UNKNOWN_ERROR.getErrorMsg(),
                            ex.getMessage());
                }
            }
        }
        return true;
    }
}

注解@AdvertiserAuthRequired

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AdvertiserAuthRequired
{
}

AuthInterceptor拦截@AuthRequired

@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor
{
    public static String API_KEY;

    public static byte[] API_KEY_SECURE_BYTES;

    private final String AUTH_HEADER = "Authorization";

    private final String TOKEN_PREFIX = "Bearer";

    @Value("${jwt.key}")
    public void setApiKey(String key)
    {
        API_KEY = key;
        API_KEY_SECURE_BYTES = Base64.getUrlEncoder().encode(API_KEY.getBytes());
    }

    private Gson gson = new GsonBuilder().create();

    @Resource
    private EbUserMapper userMapper;

    @Resource
    private EbTeamMapper teamMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    {
        boolean assignableFrom = handler.getClass().isAssignableFrom(HandlerMethod.class);
        log.debug("apply auth interceptor in method", handler.getClass().toString());
        if (assignableFrom)
        {
            AuthRequired auth = ((HandlerMethod) handler).getMethodAnnotation(AuthRequired.class);
            if (auth == null)
            {
                log.info("The method is not intercepted by AuthRequired");
                return true;
            }
            else
            {
                String jwtToken = request.getHeader(AUTH_HEADER);
                if (!StringUtils.hasLength(jwtToken) || !jwtToken.startsWith(TOKEN_PREFIX))
                {
                    log.info("The request doesn't include Bearer token");
                    return EbAuthUtil.setFailResponse(response, EbErrorCode.JWT_TOKEN_INVALID);
                }
                try
                {
                    jwtToken = jwtToken.substring(TOKEN_PREFIX.length() + 1);
                    String email = SecurityUtil.parseJwt(jwtToken);
                    //获取用户信息
                    LambdaQueryWrapper<EbUser> queryWrapper = new LambdaQueryWrapper<>();
                    EbUser ebUser = userMapper.selectOne(queryWrapper.eq(EbUser::getEmail, email));
                    if (ebUser == null || ebUser.isDeleted())
                    {
                        log.info("User with email {} already been deleted or not existed", email);
                        return EbAuthUtil.setFailResponse(response, EbErrorCode.USER_NOT_EXIST);
                    }
                    if (ebUser.getEbRole().role != EbRole.COMPANY_ADMIN.role) {
                        EbTeam team = teamMapper.selectById(ebUser.getTeamId());
                        if (team == null || team.getTeamStatus().getValue() == EbStatus.UNABLE.status)
                        {
                            log.info("Team {} is disabled now, no permission", email);
                            return EbAuthUtil.setFailResponse(response,  EbErrorCode.TEAM_DISABLED);
                        }
                    }
                    if (ebUser.getUserStatus().getValue() == EbStatus.UNABLE.status)
                    {
                        log.info("User {} is disabled now, no permission", email);
                        return EbAuthUtil.setFailResponse(response,  EbErrorCode.USER_DISABLED);

                    }
                    String requesterStr = gson.toJson(ebUser);
                    if (EbRole.TEAM_LEADER.equals(auth.roleRequired()))
                    {
                        if (ebUser.getEbRole().role == EbRole.NORMAL_USER.role)
                        {
                            return EbAuthUtil.setFailResponse(response, EbErrorCode.USER_AUTHORIZATION_ERROR);
                        }
                    }
                    else if (EbRole.COMPANY_ADMIN.equals(auth.roleRequired()))
                    {
                        if (ebUser.getEbRole().role != EbRole.COMPANY_ADMIN.role)
                        {
                            return EbAuthUtil.setFailResponse(response, EbErrorCode.USER_AUTHORIZATION_ERROR);
                        }
                    }

                    return EbAuthUtil.setRequestHeader(request, response, EbConstants.EB_REQUESTER, requesterStr);
                }
                catch (ExpiredJwtException ex)
                {
                    log.info("Jwt token expired {}", jwtToken);
                    return EbAuthUtil.setFailResponse(response, EbErrorCode.JWT_TOKEN_EXPIRE);
                }
                catch (RuntimeException ex)
                {
                    log.info("Jwt token is invalid {}", jwtToken);
                    return EbAuthUtil.setFailResponse(response, EbErrorCode.JWT_TOKEN_INVALID);
                }
            }
        }
        return true;
    }
}

注解@AuthRequired

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthRequired
{
    String permRequired() default "";

    EbRole roleRequired() default EbRole.NORMAL_USER;
}

配置类

@Configuration
public class WebInterceptorConfig extends WebMvcConfigurationSupport
{
    @Resource
    private AuthInterceptor authInterceptor;

    @Resource
    private AdvertiserAuthInterceptor advertiserAuthInterceptor;

    protected void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(authInterceptor).addPathPatterns("/ebcc/**");
        registry.addInterceptor(authInterceptor).addPathPatterns("/ebuc/**");
        registry.addInterceptor(authInterceptor).addPathPatterns("/msg-center/**");
        registry.addInterceptor(authInterceptor).addPathPatterns("/ebad/**");

        registry.addInterceptor(advertiserAuthInterceptor).addPathPatterns("/ebad/**");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("swagger-ui.html").addResourceLocations(
                "classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值