spring 使用Aspect实现对应的注解时,如何强制加载Aspect实现?

bnlyeluc  于 2022-11-21  发布在  Spring
关注(0)|答案(1)|浏览(148)

我创建了一个注解,用于验证某些安全方面是否正确。
例如,@RequireClientCertificate,它带有一个Aspect实现RequireClientCertificateAspect,用于验证是否确实将正确的HTTP头传递到了Spring REST控制器。
如果RequireClientCertificateAspect实际上被加载了,也就是说,如果它的包在@ComponentScan()中的某个地方被提到了,那么这个方法完全可以工作。
然而,如果有人忘记将这个包添加到@ComponentScan,或者方面被移动到另一个包,或者有人(意外地)从@ComponentScan中删除了包,则方面bean不会被加载,并且方面完全不会被应用。
我在一个公共库中有这个注解,由几个微服务共享,所以很容易有一个微服务不小心把它弄错了,在这种情况下,不会执行客户端证书的检查。

问题:如果使用@RequireClientCertificate注解,我如何强制执行,同时加载其相应的Aspect实现?

简化的使用示例:

@Controller
@RequestMapping(value = "/v1.0", produces = MediaType.APPLICATION_JSON_VALUE)
@RequireClientCertificate
public class SomeApiController {

    @ResponseBody
    @PostMapping("/get-token/")
    public ResponseEntity<Token> getToken() {
        return ResponseEntity.ok(...get token...);
    }
}

方面的简化版本:

@Aspect
@Component
public class RequireClientCertificateAspect {
    @Around("execution(* (@RequireClientCertificate *).*(..))")
    public Object requireClientCertificateAspectImplementation(ProceedingJoinPoint joinPoint) throws Throwable {
        ... verify request header ...
        try {
            return joinPoint.proceed();
        finally {
            ... some other things I need to check ...
        }
    }
}

我尝试过/考虑过的事情:
我可以通过向接口添加一个带有初始化器的静态字段来检测注解的“用法”。例如:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RestFactoryGatewaySecurityContext {
    static public final boolean dummy = SomeClass.checkAspectIsLoaded();
}

然而,这样的初始化器在很早的时候就被调用了,我认为SpringDI在那个阶段还没有“启动并运行”到我甚至可以可靠地确定方面bean是否被加载的程度。
另一个选择是使用@Autowired在主应用类上显式地注入RequireClientCertificateAspect bean。如果该bean不在组件扫描中,这将阻止Spring示例化该应用。
所以这确实有效,但需要有人明确地添加这个“虚拟”autowire,它本身很容易忘记,除了有点“丑陋”。

bt1cpqcv

bt1cpqcv1#

如果你使用 Spring Boot ,你可以创建自己的启动器。
创建文件META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyCustomConfiguration

然后,只需将所需的任何验证添加到配置中即可

@Configuration
public class MyCustomConfiguration{
}

您可以将您的@AutowiredRequireClientCertificateAspect插入其中,如果未定义,则会导致错误。
您可以使用@PostConstruct创建方法并执行任何所需验证。
如果你已经创建了自定义启动器,你可以在那里初始化你的bewns。
更多关于它,你可以阅读here

相关问题