关键词:
【中文标题】如何让 Shiro 在 Scala + Akka + Spray 环境中工作【英文标题】:How can i make Shiro work in Scala + Akka + Spray environment 【发布时间】:2013-07-22 09:25:57 【问题描述】:我想我没有正确理解工作流程。我正在使用 Apache Shiro 和 Stormpath 在 Scala 中编写 Web 服务。我的用户身份验证过程如下所示:
1) 从 POST 请求中获取用户数据,使用 Stormpath 进行检查,如果一切正常,重定向到某个页面:
pathPrefix("api")
path("login")
post
AuthToken.fromRequest (token: AuthToken) =>
stormpathAuth(token) subj =>
log.info("Subj ", subj.getPrincipal.toString)
redirect("/some/page", StatusCodes.Found)
在日志中没关系,Shiro 用 Stormpath 帐户返回给我一个正确的主题。接下来我要提取主题,在代码中使用它:
pathPrefix("some")
loggedInUser subject =>
path("page")
get
complete
html.render(Page.model)
..... other routes
loggedInUser
指令应该提取主题并检查它是否经过身份验证,否则重定向到登录表单。问题是它总是将我重定向到登录表单,尽管在日志中SubjectUtils.getSubject.getPrincipal
显示了正确的帐户。
更新
实际上,Spray 是建立在 Akka 之上的。所以我认为问题出在getSubject
实现背后,它目前取决于 ThreadLocal 环境。我搜索了 Shiro + Akka 主题,但没有找到任何有用的信息。
【问题讨论】:
你在用Shiro Stormpath plugin吗? 另外,这是在 Servlet 容器中运行还是在 Play 中运行! ? @LesHazlewood 是的,我正在使用 Stormpath 插件进行用户身份验证,不,我有自己的服务器和客户端,使用 Spray toolkit、spray-can 和 spray-routing 构建 @LesHazlewood 我已经更新了这个问题。我在内部使用 Akka。有什么方法可以让 Shiro 在 Akka 环境下工作? 【参考方案1】:这绝对是可能的,但您必须确保 Subject
在 Akka 组件(参与者)处理消息时可用。
我熟悉 Akka 的架构(actor / 消息传递模型),但我自己没有使用过 Akka,所以请把以下作为最佳猜测答案:
在传统的基于 Shiro 的应用程序和/或 Web 应用程序中,something 负责构建一个反映当前调用者和/或请求的 Subject
实例,然后将其绑定到当前正在执行的Thread
。这确保了在该线程执行期间对SecurityUtils.getSubject()
的任何后续调用都能正确运行。这一切都记录在 Shiro's Subject documentation 中(参见 Subject.Builder 和 Thread Association 部分)。
例如,在网络应用程序中,ShiroFilter
执行 this setup/bind/unbind logic automatically per ServletRequest。我怀疑基于 Akka 的应用程序中的某些东西(一些“框架”代码或组件)也会执行相同的设置/绑定/取消绑定逻辑。
现在有了 Akka,我相当肯定您可以使用上述文档中介绍的传统的基于线程的方法(我认为 Play!用户已经成功地做到了这一点)。但是另一种有趣的方法可能适用于 Akka 不可变消息:
构造消息时,您可以将特定于主题的信息附加到消息(例如消息“标头”)中,例如 Shiro PrincipalCollection 和身份验证状态(是否已通过身份验证)以及其他任何内容(runAs状态,随便)。
然后,当收到一条消息时,该信息将用作Subject.Builder
的输入,以创建一个Subject
实例,并在消息处理期间使用该主题实例。 Shiro Subject
实例非常轻量级,预计会在每个请求中创建和销毁(如果需要,甚至可以为每个请求多次创建和销毁),因此您无需担心 Builder 开销。
当 Subject
被构建时,你可以绑定然后解除绑定到当前正在执行的线程,或者,每个处理消息的 Actor 可以以“框架”的方式通过相同的逻辑.后一种方法根本不需要线程绑定,因为现在主题状态是在消息级别而不是线程级别维护的。
作为对这种替代(非基于线程)方法的证明,即将推出的 Shiro plugin for ActiveMQ 使用连接状态来存储 Shiro 状态,而不是线程。同样,消息状态也可以很容易地使用。
请注意,使用非基于线程的方法,下游调用者无法调用SecurityUtils.getSubject()
来获取Subject
实例。他们将不得不以另一种“框架”方式获得它。
再次,这是我在自己未使用 Akka 的情况下如何在消息传递环境(如 Akka)中工作的最大努力分析。希望这可以为您提供足够的信息,帮助您以与您的用例相关的方式解决此问题!
【讨论】:
【参考方案2】:跟进这个问题,当我遇到同样的问题时,这非常有用。主要目标是提供有关 Les Hazlewood 建议实施的一些额外信息。另一个很好的替代信息来源也是这个话题https://groups.google.com/forum/#!topic/spray-user/wpiG4SREpl0
Shiro 当前是基于线程的,这意味着它将主题信息绑定到当前线程。这是 Akka 的一个问题,因为它使用调度程序和工作线程池。
随着线程被重用,主体从一个请求泄漏到另一个请求,导致未经身份验证的请求被处理为经过身份验证的,反之亦然。
正如 Les 所建议的那样,该问题的一个可能解决方案是放弃线程绑定并将主题存储在 Akka 消息中。为此,这意味着无法使用 Shiro 的 SecurityUtils 上提供的静态方法。操作应直接在主题上完成。此外,此主题应使用 Subject.Builder 构建。
为此,您可以使用主题包装您的消息,
case class ActorMessage(subject:Subject, value: Any)
object MessageSender
def ? (actorRef: ActorRef, message: Any)(implicit subject: Subject): Future[Any] =
val resultFuture = if (!message.isInstanceOf[ActorMessage])
val actorMessage = ActorMessage(subject, message)
actorRef ask actorMessage
else actorRef ask message
for (result <- resultFuture) yield
if (result.isInstanceOf[ActorMessage])
val actorMessageResp = result.asInstanceOf[ActorMessage]
actorMessageResp.value
else result
并在收到消息时将它们解包到actor上。或者如果它是请求条目参与者,则初始化主题。
abstract class ShiroActor extends Actor
implicit var shiroSubject: Subject = (new Subject.Builder).buildSubject
override def aroundReceive(receive: Actor.Receive, msg: Any): Unit =
if (msg.isInstanceOf[ActorMessage])
val actorMessage = msg.asInstanceOf[ActorMessage]
shiroSubject = actorMessage.subject
receive.applyOrElse(actorMessage.value, unhandled)
else
shiroSubject = (new Subject.Builder).buildSubject
receive.applyOrElse(msg, unhandled)
现在要使用它,实现的 Actor 必须扩展 ShiroActor 并在 Actor 之间交换消息,您必须使用 MessageSender,而不是 ActorRef 的 ask 或 tell 方法。
要登录主题、检查权限、角色等,您现在可以使用 actor 上可用的主题。像这样,
shiroSubject.login(new AuthenticationToken(principal, credentials))
这假设登录是在请求条目参与者上完成的,并且主题只是共享以检查后续参与者的权限。但我确信它可以很容易地适应双向更新演员的 shiroSubject。
希望这是一个有用的资源,因为似乎几乎不可能找到这两个框架之间集成的示例。
【讨论】:
使用 Scala/Akka 在 JVM 中进行高频交易
】使用Scala/Akka在JVM中进行高频交易【英文标题】:HighFrequencyTradingintheJVMwithScala/Akka【发布时间】:2012-04-1415:24:23【问题描述】:让我们想象一个Java中的假设HFT系统,需要(非常)低延迟,由于不变性(Scala?),有许多短命的... 查看详情
Scala、Akka、Spray:如何在处理前验证 json 数据?
】Scala、Akka、Spray:如何在处理前验证json数据?【英文标题】:Scala,Akka,Spray:Howtovalidatejsondatabeforeprocessing?【发布时间】:2015-03-3117:29:31【问题描述】:当所有输入都有效时,我可以处理这个json,即使用有效的键(包括大小写)... 查看详情
如何在scala akka(spray)中为rest服务编写测试用例
】如何在scalaakka(spray)中为rest服务编写测试用例【英文标题】:howtowritetestcaseforrestserviceinscalaakka(spray)【发布时间】:2016-04-2416:38:22【问题描述】:如何模拟HttpRespose?我正在使用scalla、akka和spray来调用以json响应的rest服务,我... 查看详情
Scala如何使用akka actor有效地处理超时操作
】Scala如何使用akkaactor有效地处理超时操作【英文标题】:Scalahowtouseakkaactorstohandleatimingoutoperationefficiently【发布时间】:2013-07-1111:46:53【问题描述】:我目前正在使用Rhino在一个安静的服务中评估javascript脚本。我希望有一个评估... 查看详情
如何在 Scala Akka 中停止 system.scheduler.schedule
】如何在ScalaAkka中停止system.scheduler.schedule【英文标题】:Howtostopasystem.scheduler.scheduleinScalaAkka【发布时间】:2021-11-1503:27:45【问题描述】:我目前有一个方法可以创建一个调度程序,以设定的时间间隔向我的演员发送消息。但是... 查看详情
如何使用 scala 2.9.x 运行 akka 2.1-snapshots?
】如何使用scala2.9.x运行akka2.1-snapshots?【英文标题】:Howcanrunakka2.1-snapshotswithscala2.9.x?【发布时间】:2012-07-2420:32:36【问题描述】:当将akka从1.2升级到akka2.0.2时,我无法实现camel,因为akka2.0.2不支持akka-camel,我尝试使用akka2.1-snap... 查看详情
如何理解 AKKA 中使用的这种 CCAS 锁定机制?
】如何理解AKKA中使用的这种CCAS锁定机制?【英文标题】:HowtounderstandthisCCASlockingmachanizionusedinAKKA?【发布时间】:2011-09-0516:01:55【问题描述】:我刚刚在akka中遇到了一段代码。https://codereview.scala-lang.org/fisheye/browse/~raw,r=25521/scala-... 查看详情
scala框架akka学习(代码片段)
...Actor的关系Akka模型介绍Actor模型的优点Akka模型的核心概念如何创建Actor添加依赖在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法**akka的架构原理**创建Actor的步骤receive方法介绍ActorSystemactorOf方法actorOf方法的参... 查看详情
在 Play Framework 2.4 中为 Scala 实现 Akka
】在PlayFramework2.4中为Scala实现Akka【英文标题】:ImplementingAkkainPlayFramework2.4forScala【发布时间】:2015-10-2010:06:13【问题描述】:我正在尝试复制IntegratingwithAkka,Play2.4forScaladoc中提出的基本示例。但是我很难将最后的部分放在一起...... 查看详情
在线程“main”中获取akka流代码时出错,异常java.lang.noclassdeffounderror:scala/function1$class
当我运行akka流代码时,我遇到了Java错误:**线程“主”中的异常java.lang.NoClassDefFoundError:scala/Function1$class在akka.stream.Supervision$$anon$1。(Supervision.scala:57)在akka.stream.Supervision$。(Supervision.scala:57)在akka.stre 查看详情
如何在akka中扩展超级演员的行为
】如何在akka中扩展超级演员的行为【英文标题】:Howextendbehaviourofsuperactorinakka【发布时间】:2017-09-2907:29:28【问题描述】:我想使用akkaactor实现CRUD操作。我是akka新手,所以不知道akkaactor的设计基础。我想在多个子actor中分享akka... 查看详情
在 scala/akka 的计算之间检查参与者的消息查询
】在scala/akka的计算之间检查参与者的消息查询【英文标题】:Checkingmessagequerybyactorinbetweencalculationsinscala/akka【发布时间】:2021-12-1917:52:22【问题描述】:我有一个演员,当他收到一条消息时,他开始循环计算,并且他做了一段... 查看详情
在 Scala Akka 期货中,map 和 flatMap 有啥区别?
】在ScalaAkka期货中,map和flatMap有啥区别?【英文标题】:InScalaAkkafutures,whatisthedifferencebetweenmapandflatMap?在ScalaAkka期货中,map和flatMap有什么区别?【发布时间】:2011-10-0500:34:46【问题描述】:在普通的Scala映射和flatMap中,flatMap将... 查看详情
部署 Scala/Akka 微服务的规范方法是啥?
...几十个这样的微服务(大多数是基于Akka的),我不确定如何最好地管理它们的部署。具体来说,它们被构建为彼此独立,并且尽可能专业化和分布式。我的问题 查看详情
如何改善响应式 kafka(Scala 加 Akka Streams)的缓慢性能?
】如何改善响应式kafka(Scala加AkkaStreams)的缓慢性能?【英文标题】:Howtoimproveslowperformanceofreactive-kafka(ScalaplusAkkaStreams)?【发布时间】:2016-07-1712:45:03【问题描述】:我正在将我的项目从RabbitMQ转移到Kafka,并试图了解reactive-kafka... 查看详情
如何使用 AKKA-HTTP、spray-json、oauth2 和 slick 优化 scala REST api?
】如何使用AKKA-HTTP、spray-json、oauth2和slick优化scalaRESTapi?【英文标题】:HowtooptimizescalaRESTapiusingAKKA-HTTP,spray-json,oauth2andslick?【发布时间】:2017-01-3111:11:31【问题描述】:我使用AKKA-HTTP、spray-json和Slick在scala中创建了一个RESTapi。对... 查看详情
使用 Akka 进行 Scala 折叠
】使用Akka进行Scala折叠【英文标题】:ScalafoldingusingAkka【发布时间】:2011-09-1911:52:01【问题描述】:我在Java中实现了我所谓的“可折叠队列”,即ExecutorService使用的LinkedBlockingQueue。这个想法是每个任务作为一个唯一的id,如果... 查看详情
scala-unit7-scala并发编程模型akka
...高并发、分布式、并且容错的应用工具包; Akka使用Scala语言编写,同时它提供了Scala和Java的开发接口,Akka可以开发一些高并发的程序。 二、Akka的Acor模型 A卡卡处理并发的方法基于actor模型,在基于actor的系统中,所... 查看详情