Spring Boot 实现通用 Auth 认证的 4 种方式
点击上方“Java技术江湖”,选择“设为星标”
回复”666“获取全网最热的Java核心知识点整理
文章介绍了spring-boot中实现通用auth的四种方式,包括 传统AOP、拦截器、参数解析器和过滤器,并提供了对应的实例代码,最后简单总结了下他们的执行顺序。
前言
通用的 appkey 白名单校验功能,希望它的扩展性更好一些。传统AOP
实现
使用 @Aspect声明一下切面类WhitelistAspect;在切面类内添加一个切点 whitelistPointcut(),为了实现此切点灵活可装配的能力,这里不使用execution全部拦截,而是添加一个注解@Whitelist,被注解的方法才会校验白名单。在切面类中使用 spring 的 AOP 注解 @Before声明一个通知方法checkWhitelist()在 Controller 方法被执行之前校验白名单。
@Aspect
public class WhitelistAspect {
   
 @Before(value = "whitelistPointcut() && @annotation(whitelist)")
 public void checkAppkeyWhitelist(JoinPoint joinPoint, Whitelist whitelist) {
     checkWhitelist();
     // 可使用 joinPoint.getArgs() 获取Controller方法的参数
     // 可以使用 whitelist 变量获取注解参数
 }
   
   
 @Pointcut("@annotation(com.zhenbianshu.Whitelist)")
 public void whitelistPointCut() {
 }
}
@Whitelist 注解实现功能。扩展
uid() 等方法,实现自定义校验。execution(执行方法) 、bean(匹配特定名称的 Bean 对象的执行方法)等切点声明方法和 @Around(在目标函数执行中执行) 、@After(方法执行后) 等通知方法。Interceptor
HandlerInterceptor 接口。实现
定义拦截器类 AppkeyInterceptor类并实现 HandlerInterceptor 接口。实现其 preHandle()方法;在 preHandle 方法内通过注解和参数判断是否需要拦截请求,拦截请求时接口返回 false;在自定义的 WebMvcConfigurerAdapter类内注册此拦截器;
AppkeyInterceptor 类如下:@Component
public class WhitelistInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Whitelist whitelist = ((HandlerMethod) handler).getMethodAnnotation(Whitelist.class);
        // whitelist.values(); 通过 request 获取请求参数,通过 whitelist 变量获取注解参数
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  // 方法在Controller方法执行结束后执行
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  // 在view视图渲染完成后执行
    }
}
扩展
WebMvcConfigurerAdapter 对它进行配置。需要注意,继承它的的 MvcConfiguration 需要在 ComponentScan 路径下。@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new WhitelistInterceptor()).addPathPatterns("/*").order(1);
        // 这里可以配置拦截器启用的 path 的顺序,在有多个拦截器存在时,任一拦截器返回 false 都会使后续的请求方法不再执行
    }
}
200,但响应数据为空。Spring Boot 基础教程和示例源码在这里学习:https://github.com/javastacks/javastack,非常全了。ArgumentResolver
@RequestParam 注解就有它的影子,使用它,我们可以将参数在进入Controller Action之前就组合成我们想要的样子。ResolverList, 在请求到达时,Spring 发现有自定义类型参数(非基本类型), 会依次尝试这些 Resolver,直到有一个 Resolver 能解析需要的参数。要实现一个参数解析器,需要实现 HandlerMethodArgumentResolver 接口。实现
定义自定义参数类型
AuthParam,类内有 appkey 相关字段;定义
AuthParamResolver并实现 HandlerMethodArgumentResolver 接口;实现
supportsParameter()接口方法将 AuthParam 与 AuthParamResolver 适配起来;实现
resolveArgument()接口方法解析 reqest 对象生成 AuthParam 对象,并在此校验 AuthParam ,确认 appkey 是否在白名单内;在 Controller Action 方法上签名内添加 AuthParam 参数以启用此 Resolver;
@Component
public class AuthParamResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(AuthParam.class);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Whitelist whitelist = parameter.getMethodAnnotation(Whitelist.class);
        // 通过 webRequest 和 whitelist 校验白名单
        return new AuthParam();
    }
}
扩展
WebMvcConfigurerAdapter内配置:@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List argumentResolvers) {
        argumentResolvers.add(new AuthParamResolver());
    }
}
 Filter。Filter
javax.servlet.Filter接口即可。public class WhitelistFilter implements javax.servlet.Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
  // 初始化后被调用一次
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
     // 判断是否需要拦截
       chain.doFilter(request, response); // 请求通过要显示调用
    }
    @Override
    public void destroy() {
     // 被销毁时调用一次
    }
}
扩展
Filter 也需要显示配置:
@Configuration
public class FilterConfiguration {
    @Bean
    public FilterRegistrationBean someFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new WhitelistFilter());
        registration.addUrlPatterns("/*");
        registration.setName("whitelistFilter");
        registration.setOrder(1); // 设置过滤器被调用的顺序
        return registration;
    }
}
小结
转自:枕边书
链接:https://zhenbianshu.github.io/
- EOF -
关注公众号【Java技术江湖】后回复“PDF”即可领取200+页的《Java工程师面试指南》
强烈推荐,几乎涵盖所有Java工程师必知必会的知识点,不管是复习还是面试,都很实用。

评论
