在未经授权的异步请求上播放框架服务器端重定向

时间:2017-03-13 08:49:18

标签: http redirect playframework promise single-page-application

我在单页面应用程序中使用Play Framework / Reactjs。 身份验证是使用ActionBuilders构建的,因此从浏览器发出的任何异步请求都受到" AuthorizedAction"的保护。

以下是ActionBuiler的invokeBlock

的实现
override def invokeBlock[A](request: Request[A], block: (AuthorizedRequest[A]) ⇒ Future[Result]): Future[Result] = {
  val maybeToken = request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey))

  maybeToken match {
    case Some(token) => cache.get[Long](token) match {
      case Some(u_id) =>
        val user = User.findByID(u_id).get
        val req = AuthorizedRequest(request, user)
        block(req)
      case None => Future.successful(Unauthorized)  // REDIRECT HERE
    }
    case None => Future.successful(Unauthorized)  // REDIRECT HERE
  }
}

这很有效,但有一个例外:我希望不要简单地返回Unauthorized来重定向到登录页面。因为到目前为止,如果令牌超时,并且用户导致异步请求被触发,它将在控制台中出错,并且页面看起来会破碎。

方法1:

将以上两条Future.successful行替换为:

Future.successful(Redirect("/login"))

这实际上会调用/login路由的控制器,但URL不会更改。相反,触发的异步请求的响应包含data =

`<!DOCTYPE html ...

这是异步请求的示例,其response.data包含以下屏幕截图文本:

axios('/ping')
.then((response) => {
  let userID = response.data; // contains junk
  store.dispatch(SomeAction.xyz(userID))
})
.catch((error) => {
  browserHistory.push('/login');
})

enter image description here

看起来我在这里缺少一些关键的东西。任何想法如何从这里开始?

方法2:

在前端

上使用React路由器browserHistory.push('/login') 在所有异步请求中#39; .catch()

虽然我希望尽可能避免这种情况,但方法1可以成功运作。

由于

1 个答案:

答案 0 :(得分:0)

事实证明,这与Play Framework有关,而与HTTP代码/响应有关,以及浏览器如何解释它们。

似乎我们不应该将重定向返回到异步请求,因为它们会导致问题中方法1的问题。

相反,人们一直在建议以下之一:

  • 返回Ok/200,其中包含一些特定标题,指示前端必须进行重定向
  • 返回一些自定义错误代码,例如Status(xyz)前端代码将理解并解释为重定向到某个路由的请求。

选择适当的HTTP代码是另一个主题,从上面的两个选项中,我们有三个选择:

  • 200或自定义2xx代码,解释为成功并在承诺中处理
  • 3xx自定义代码可能看似合适,因为我们要求重定向
  • 401或自定义4xx代码。从技术上讲,传入的异步请求是未经授权的(401),因此应该是error级响应。

关键部分是处理响应代码似乎必须在问题的方法2的前端。

我倾向于默认的401