我正在使用SDL OData Framework(https://github.com/sdl/odata)和Spring Boot开发OData服务(Java)。
通过Spring Security向应用添加安全性时,我遇到了一些问题。
在某些实现SDL框架提供的接口的类中,当使用“@PreAuthorize(”hasRole('ADMIN')“)”注释方法时,我会收到错误。
控制台输出是:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:378) ~[spring-security-core-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:222) ~[spring-security-core-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:64) ~[spring-security-core-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at com.sun.proxy.$Proxy100.getStrategy(Unknown Source) ~[na:na]
at com.sdl.odata.processor.datasource.factory.DataSourceFactoryImpl.getStrategy(DataSourceFactoryImpl.java:75) ~[odata_processor-2.2-SNAPSHOT.jar:2.2-SNAPSHOT]
at com.sdl.odata.processor.ODataQueryProcessorImpl.query(ODataQueryProcessorImpl.java:85) ~[odata_processor-2.2-SNAPSHOT.jar:2.2-SNAPSHOT]
at com.sdl.odata.service.actor.ODataQueryProcessorActor$$anonfun$receive$1.applyOrElse(ODataQueryProcessorActor.scala:38) ~[odata_service-2.2-SNAPSHOT.jar:2.2-SNAPSHOT]
at akka.actor.Actor$class.aroundReceive(Actor.scala:480) ~[akka-actor_2.11-2.4.1.jar:na]
at com.sdl.odata.service.actor.ODataQueryProcessorActor.aroundReceive(ODataQueryProcessorActor.scala:29) ~[odata_service-2.2-SNAPSHOT.jar:2.2-SNAPSHOT]
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526) [akka-actor_2.11-2.4.1.jar:na]
at akka.actor.ActorCell.invoke(ActorCell.scala:495) [akka-actor_2.11-2.4.1.jar:na]
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257) [akka-actor_2.11-2.4.1.jar:na]
at akka.dispatch.Mailbox.run(Mailbox.scala:224) [akka-actor_2.11-2.4.1.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_74]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_74]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_74]
SDL框架的部分代码是用Scala编写的,并使用Akka工具包。
我认为异常 AuthenticationCredentialsNotFoundException 与SDL Framework所需的实现类在不同的线程(线程本地)中运行的事实相关,而不是创建安全上下文的线程。
所以,问题是:是这样吗?如果是,我如何获得这些类中的安全上下文?
源代码位于:https://github.com/diegocairone/sdlpoc-jpa-querydsl/tree/master/sdlpocjpa
答案 0 :(得分:0)
据我所知,Spring使用ThreadLocal在组件之间传递上下文,在Akka中无法保证相同的线程将执行处理消息流所涉及的每个接收块。
您可以手动提取安全上下文,同时仍然在Spring管理的线程中,将其传递到您的演员之间的消息内,并在处理消息之前在ThreadLocal
中恢复它(不要忘记之后删除它,否则它将在消息之间泄漏)。