使用null身份验证获取Spring Security Context

时间:2016-07-26 15:21:48

标签: spring-security spring-boot akka

我正在使用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

1 个答案:

答案 0 :(得分:0)

据我所知,Spring使用ThreadLocal在组件之间传递上下文,在Akka中无法保证相同的线程将执行处理消息流所涉及的每个接收块。

您可以手动提取安全上下文,同时仍然在Spring管理的线程中,将其传递到您的演员之间的消息内,并在处理消息之前在ThreadLocal中恢复它(不要忘记之后删除它,否则它将在消息之间泄漏)。