Spring Security子线程上下文

Lan*_*lot 6 java multithreading spring-security

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

现在我和我的团队一直在调整代码和处理方法,我不认为我们可以在没有切片并异步执行每个切片的情况下获得更好的性能.

问题是当我尝试将它分割并将工作分发给子线程时,使用来自java.util.concurrent的线程池,当执行这些时,我得到有关安全上下文的错误消息.

这是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)
Run Code Online (Sandbox Code Playgroud)

我知道从请求中生成线程并不是一个好习惯...但是我们此时已经没有想法了,每个工作线程的测量时间不应超过几秒钟.此外,预计此功能仅由1或2名专用用户每周使用一次.

有没有办法将securityContext传递给子线程或类似的允许这些线程执行的东西?

谢谢

kro*_*old 2

我们通常会执行以下操作: 在最初的 spring 管理线程中执行以下操作

Locale locale = LocaleContextHolder.getLocale();
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
Run Code Online (Sandbox Code Playgroud)

现在您需要将这两个值放在新线程可以找到的地方。然后你就可以:

 LocaleContextHolder.setLocale( locale, true);
 RequestContextHolder.setRequestAttributes( ra, true);
Run Code Online (Sandbox Code Playgroud)

在你的新线程中。尽管我不确定这是否是受支持的方法,但它总是运行良好。