怎么在其他服务中拿到SpringContextHolder

做了一个基于nacos,seata的微服务项目,现在想把服务拆分开来,遇到了一个问题,鉴权框架使用的SpringSecurity,我想在gateway中的过滤器直接处理鉴权的问题,但是gateway框架没有SpringContextHolder,我无法把认证信息塞进去,就算塞进去了,其他微服务没有用SpringSecurity框架也拿不到认证信息

使用全局过滤器:Gateway框架可以使用全局过滤器来处理请求,这样可以在请求经过Gateway之前进行一些自定义的处理,包括鉴权。你可以创建一个实现了GlobalFilter接口的全局过滤器,并加上@Component注解使其成为Spring管理的Bean。在过滤器中,你可以通过调用ServerWebExchange对象的方法来获取请求头或请求参数中的认证信息,并进行相应的鉴权处理; 使用自定义注解:另一种方式是使用自定义注解。你可以创建一个自定义注解,例如@AuthorizationRequired,用于标识需要进行鉴权的接口或方法。然后,编写一个Aspect切面,在切面中获取请求中的认证信息,并进行鉴权处理。Aspect切面可以通过@Around注解来拦截被@AuthorizationRequired注解标识的方法,然后在切面中进行相应的鉴权逻辑,如检查token、验证权限等。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答由chatgpt基于相关博客总结生成:

    如何在其他服务中获取SpringContextHolder的实例?

    如果在其他服务中需要获取SpringContextHolder的实例,可以通过以下步骤解决该问题。

    1. 首先,在其他微服务项目中添加spring-context依赖项。在Maven项目中,可以在pom.xml文件中添加以下依赖项:
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>{spring版本号}</version>
    </dependency>
    
    1. 创建一个名为SpringContextHolder的类,并添加一个静态方法来获取该类的实例。这个类将担任一个中央容器的角色,负责保存和提供Spring的ApplicationContext实例。代码如下:
    import org.springframework.context.ApplicationContext;
    
    public class SpringContextHolder {
    
        private static ApplicationContext applicationContext;
    
        public static void setApplicationContext(ApplicationContext applicationContext) {
            SpringContextHolder.applicationContext = applicationContext;
        }
    
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    }
    
    1. 在每个微服务项目的启动类中,通过调用SpringApplication的addListeners方法,并将SpringContextHolder的实例传递给它。这样,当应用程序启动时,SpringContextHolder将获得ApplicationContext实例并保存起来。代码如下:
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class YourApplication {
    
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(YourApplication.class);
            ConfigurableApplicationContext context = application.run(args);
    
            // 设置ApplicationContext到SpringContextHolder
            SpringContextHolder.setApplicationContext(context);
        }
    }
    
    1. 在需要获取SpringContextHolder实例的地方,可以通过调用SpringContextHolder.getApplicationContext()来获取ApplicationContext实例,从而获取任何需要的bean。例如,在gateway的过滤器中可以通过以下代码获取当前用户的认证信息:
    import org.springframework.context.ApplicationContext;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.web.server.WebFilter;
    import reactor.core.publisher.Mono;
    
    public class AuthFilter implements WebFilter {
    
        private ApplicationContext applicationContext;
    
        public AuthFilter(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
            // 获取当前认证信息
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    
            // 其他处理逻辑...
    
            return chain.filter(exchange);
        }
    }
    

    上述代码在AuthFilter的构造函数中接收了一个ApplicationContext实例,该实例可以通过SpringContextHolder.getApplicationContext()获取。

    这样,在其他微服务项目中,就可以通过SpringContextHolder的实例获取ApplicationContext,以访问和使用其他微服务共享的bean,例如获取和传递认证信息。

    希望这个解决方案对你有帮助,如果有任何问题,请随时向我提问!


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^