Spring security 从线程调用的假客户端+;春季安全

Spring security 从线程调用的假客户端+;春季安全,spring-security,spring-cloud,java-threads,netflix-feign,Spring Security,Spring Cloud,Java Threads,Netflix Feign,我打电话给一个外国客户。它工作得很好,直到我尝试将假客户端放在线程中(简化版): 当我尝试这样做时,我得到(由真实版本打印,而不是上面的简化版本): feignUserClient是@Autowired(我试着将其转换为final,并使用构造函数注入它,但没有什么区别——无论如何,当代码执行时,它的值不是null) 更多信息: 外部接口: 另一个类调用外部接口。。。没关系。我在几个不同的类中尝试了它(所有类都用@RestController或@Service注释)。如果我从线程调用Usuario

我打电话给一个外国客户。它工作得很好,直到我尝试将假客户端放在线程中(简化版):

当我尝试这样做时,我得到(由真实版本打印,而不是上面的简化版本):

feignUserClient
是@Autowired(我试着将其转换为final,并使用构造函数注入它,但没有什么区别——无论如何,当代码执行时,它的值不是null)

更多信息:

外部接口:
另一个类调用外部接口。。。没关系。我在几个不同的类中尝试了它(所有类都用
@RestController
@Service
注释)。如果我从线程调用
UsuarioFeign.findByEmail
,它就会停止工作。

最后,问题与Spring安全上下文有关。根据设计,“安全性存储在每个线程的基础上”。这意味着,如果您在新线程中需要类似于安全上下文的内容,您将无法获得它

在文档中,您可以找到将其作为参数传输到新线程的方法:

Runnable originalRunnable = new Runnable() {
    public void run() {
        // invoke secured service
    }
};

SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
    new DelegatingSecurityContextRunnable(originalRunnable, context);

new Thread(wrappedRunnable).start();

最后,问题与Spring安全上下文有关。根据设计,“安全性存储在每个线程的基础上”。这意味着,如果您在新线程中需要类似于安全上下文的内容,您将无法获得它

在文档中,您可以找到将其作为参数传输到新线程的方法:

Runnable originalRunnable = new Runnable() {
    public void run() {
        // invoke secured service
    }
};

SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
    new DelegatingSecurityContextRunnable(originalRunnable, context);

new Thread(wrappedRunnable).start();

你能添加整个
AlfaTutoriaApplication
类吗?刚刚添加了,@ryan。我正在努力追查这个问题。我用简单的线程构建了两个简单的假应用程序。成功了。所以简单的线程不是问题所在。我还在努力。现在我要更新Spring boot,接下来,查找嵌套线程。我从主题@ryan中删除了
AlfaTutoriaApplication
类。事实上,它给了我一个关于真正问题是什么的重要线索(但谢谢你的提问——简单的复制和粘贴动作称为我的安全部分的提示)。你能添加整个
AlfaTutoriaApplication
类吗?刚刚添加了,@ryan。我正在努力追查这个问题。我用简单的线程构建了两个简单的假应用程序。成功了。所以简单的线程不是问题所在。我还在努力。现在我要更新Spring boot,接下来,查找嵌套线程。我从主题@ryan中删除了
AlfaTutoriaApplication
类。事实上,它给了我一个关于真正问题是什么的重要线索(但感谢您的提问-简单的复制和粘贴操作调用了我对安全部分的提示)。欢迎使用堆栈溢出!请不要把你的源代码扔在这里。对你的答案要和蔼可亲,尽量给它一个很好的描述,这样其他人就会喜欢它并投赞成票。请参阅:欢迎使用堆栈溢出!请不要把你的源代码扔在这里。对你的答案要和蔼可亲,尽量给它一个很好的描述,这样其他人就会喜欢它并投赞成票。见:
@FeignClient(name = "authUsers", url = br.alfa.tutoria.config.Url.AUTH_SERVER)
public interface UsuarioFeign {
    @RequestMapping(value = "/user-search-by-email", method = RequestMethod.POST)
    public User findByEmail(String email);
}
Runnable originalRunnable = new Runnable() {
    public void run() {
        // invoke secured service
    }
};

SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
    new DelegatingSecurityContextRunnable(originalRunnable, context);

new Thread(wrappedRunnable).start();
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

public class SecurityContextRunnable implements Runnable {
    private Runnable runnable;
    private RequestAttributes requestAttributes;
    private SecurityContext securityContext;
    private SecurityContext originalSecurityContext;

    private SecurityContextRunnable(Runnable runnable) {
        this(runnable, RequestContextHolder.getRequestAttributes());
    }

    private SecurityContextRunnable(Runnable runnable, RequestAttributes requestAttributes) {
        this(runnable, requestAttributes, null);
    }

    private SecurityContextRunnable(Runnable runnable, RequestAttributes requestAttributes, SecurityContext securityContext) {
        try {
            if (securityContext == null) {
                securityContext = SecurityContextHolder.getContext();
            }
        } catch (Exception e) {

        }

        this.runnable = runnable;
        this.requestAttributes = requestAttributes;
        this.securityContext = securityContext;
    }

    @Override
    public void run() {
        this.originalSecurityContext = SecurityContextHolder.getContext();
        try {
            SecurityContextHolder.setContext(securityContext);
            RequestContextHolder.setRequestAttributes(requestAttributes);
            runnable.run();
        } finally {
            SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
            if (emptyContext.equals(originalSecurityContext)) {
                SecurityContextHolder.clearContext();
            } else {
                SecurityContextHolder.setContext(originalSecurityContext);
            }
            this.originalSecurityContext = null;
        }
    }

    public static SecurityContextRunnable create(Runnable runnable) {
        return new SecurityContextRunnable(runnable);
    }

    public static SecurityContextRunnable create(Runnable runnable, RequestAttributes requestAttributes) {
        return new SecurityContextRunnable(runnable, requestAttributes);
    }

    public static SecurityContextRunnable create(Runnable runnable, RequestAttributes requestAttributes, SecurityContext securityContext) {
        return new SecurityContextRunnable(runnable, requestAttributes, securityContext);
    }

}


Runnable originalRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            feignUserClient.findByEmail("someEmail@address.com");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

SecurityContextRunnable wrappedRunnable = SecurityContextRunnable.create(originalRunnable);
new Thread(wrappedRunnable).start();