Spring Security子线程上下文 [英] Spring Security Child Thread Context

查看:107
本文介绍了Spring Security子线程上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在使用Spring Security来开发这个Spring MVC应用程序.在某些情况下,我的控制器的响应时间过长,我遇到了性能问题. 这是由于一种处理方法,根据某些用户输入,该方法可能需要处理大量数据.

So I'm working on this Spring MVC application using Spring Security. I've been hitting a performance problem in some instances where my controller is taking way too long to respond. This is due to a processing method that can take a huge amount of data in to process, based on some user input.

现在,我一直在与我的团队一起对该处理方法进行一些微调,我认为如果不对它进行切片和异步执行每个切片,我们将无法从中获得更好的性能.

Now I've been tweaking the code a bit in and around that processing method with my team and I don't think we can get much better performance out of that without slicing it and executing each slice asynchronously.

问题是,当我尝试使用java.util.concurrent中的线程池对它进行切片并将工作分配给子线程时,执行这些消息时会收到有关安全上下文的错误消息.

The problem is when I try to slice it and distribute the work to child threads, using a threadpool from java.util.concurrent, I get error messages about the security context when those execute.

这是stacktrace的摘录:

Here is an extract of the stacktrace:

Exception in thread "pool-1-thread-3" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342)
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254)
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63)
Exception in thread "pool-1-thread-4"   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy63.batchSaveCampaignpayment(Unknown Source)
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
    at java.lang.Thread.run(Thread.java:595)
org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342)
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254)
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy63.batchSaveCampaignPayment(Unknown Source)
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
    at java.lang.Thread.run(Thread.java:595)
Exception in thread "pool-1-thread-5" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342)
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254)
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy63.batchSaveCampaignPayment(Unknown Source)
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
    at java.lang.Thread.run(Thread.java:595)

我知道从请求中生成线程不是一个好习惯……但是我们在这一点上已经花光了,根据我们的测量,每个工作线程所花费的时间不应超过几秒钟.另外,预计每周只有1个或2个专用用户可以使用此功能.

I know it's not good practice to spawn threads from a request... but we've ran out of ideas at this point and each worker thread shouldn't take more than a handful of seconds by our measurements. Also it is expected that this feature is going to be used by 1 or 2 dedicated users once a week only.

是否有一种方法可以将securityContext传递给子线程或类似的允许子线程执行的事情?

Is there a way to pass the securityContext to the child threads or anything similar that would allow those threads to execute?

谢谢

推荐答案

当我遇到类似的问题时,我发现了两个解决方案:

I found two solutions when I had a similar problem:

解决方案1 ​​ 将SecurityContextHolder的策略更改为 MODE_INHERITABLETHREADLOCAL

Solution 1 Change strategy of SecurityContextHolder to MODE_INHERITABLETHREADLOCAL

您可以通过这种方式完成

You may do it in such way

<beans:bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <beans:property name="targetClass"
              value="org.springframework.security.core.context.SecurityContextHolder"/>
    <beans:property name="targetMethod" value="setStrategyName"/>
    <beans:property name="arguments" value="MODE_INHERITABLETHREADLOCAL"/>
</beans:bean>

解决方案2 使用 DelegatingSecurityContextRunnable DelegatingSecurityContextExecutor DelegatingSecurityContextExecutor . Spring并发支持文档中对此解决方案进行了很好的描述.

这篇关于Spring Security子线程上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆