如何让 Shiro 在 Scala + Akka + Spray 环境中工作

     2023-02-27     119

关键词:

【中文标题】如何让 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.BuilderThread 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的系统中,所... 查看详情