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();