spring-cloud通过注解忽略用户校验

  •  需要用 token 来获取当前用户
  •   需要在方法中自动注入用户
    不是所有接口都
  •   需要控制登录状态

分析

  • 利用拦截器来统一处理 token 
  • 需要在拦截器需要处理某些不需要验证 token 的接口 
  • 自动注入用户实体类

方案

  • 添加自定义注解两个,一个用于标识用户实体类入参,一个用户标识是否需要注入用户实体类
  • 添加拦截器,从 http header 里获取 token 从而获取当前登录用户,将登陆用户存到 HttpServletRequest 的 Attribute 中 
  • 添加参数解析器实现 HandlerMethodArgumentResolver 
  • 接口
    注册拦截器和参数解析器在 WebMvcConfigurerAdapter 中

代码
1、添加自定义注释 @CurrentUser 用于标识用户实体类入参,参数级注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
}

2、添加自定义注释 @IgnoreSecurity 用于标识是否忽略登录检查,方法级注解

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

3、添加拦截器 AuthInterceptor 继承字 HandlerInterceptorAdapter 重写 preHandle 方法

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler) throws Exception {

        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        /*if (ModeEnum.DEVELOP == ModeEnum.valueOf(mode) || ModeEnum.SNAPSHOT == ModeEnum.valueOf(mode)) {
            return true;
        }*/


        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String requestPath = request.getRequestURI();
//        log.debug("requestIp: " + getIpAddress(request));
        log.debug("Method: " + method.getName() + ", IgnoreSecurity: " + method.isAnnotationPresent(IgnoreSecurity.class));
        log.debug("requestPath: " + requestPath);
        /*if (requestPath.contains("/v2/api-docs") || requestPath.contains("/swagger") || requestPath.contains("/configuration/ui")) {
            return true;
        }
        if (requestPath.contains("/error")) {
            return true;
        }*/
        if (method.isAnnotationPresent(IgnoreSecurity.class)) {
            return true;
        }
        String token = request.getHeader("ACCESS_TOKEN");
        log.debug("token: " + token);
        if (StringUtils.isEmpty(token)) {
            throw new DajiujiaoException(ResultEnum.ACCESS_TOKEN_ERROR);
        }
        UserLogInfoDto userInfo = userLogService.getUserByToken(token);
        request.setAttribute("currentUser", userInfo);
        return true;

    }

4、添加参数解析器 CurrentUserMethodArgumentResolver

public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().isAssignableFrom(UserInfo.class) && parameter.hasParameterAnnotation(CurrentUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        UserLogInfoDto userInfo = (UserLogInfoDto) webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_REQUEST);
        if (userInfo != null) {
            return userInfo;
        }
        throw new MissingServletRequestPartException("currentUser");
    }
}

5、注册拦截器和参数解析器在 WebMvcConfigurerAdapter 中,需要注意,拦截器中引用了 UserService 所以在注册时需要使用 @Bean 的形式以告诉 Spring 注入

@Configuration
public class AppAuthConfiguration extends WebMvcConfigurerAdapter {

    //关键,将拦截器作为bean写入配置中
    @Bean
    public AppAuthInterceptor getSecurityInterceptor() {
        return new AppAuthInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        InterceptorRegistration ir = registry.addInterceptor(getSecurityInterceptor());
        // 配置拦截的路径
        ir.addPathPatterns("/api/**");
        // 配置不拦截的路径
//        ir.excludePathPatterns("**/swagger-ui.html");
        // 还可以在这里注册其它的拦截器
//        registry.addInterceptor(new AppAuthInterceptor()).addPathPatterns("/api/**");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(currentUserMethodArgumentResolver());
        super.addArgumentResolvers(argumentResolvers);
    }

    @Bean
    public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
        return new CurrentUserMethodArgumentResolver();
    }

}

上述代码添加完毕后就可以开始进行测试接口了
新建一个 Controller 用于测试



在方法上面添加@IgnoreSecurity注解表示不对这个接口进行验证

在参数添加@CurrentUser UserInfo userInfo来获取当前登录用户

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值