我在单页面应用程序中使用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');
})
看起来我在这里缺少一些关键的东西。任何想法如何从这里开始?
方法2:
在前端上使用React路由器browserHistory.push('/login')
在所有异步请求中#39; .catch()
虽然我希望尽可能避免这种情况,但方法1可以成功运作。
由于
答案 0 :(得分:0)
事实证明,这与Play Framework有关,而与HTTP代码/响应有关,以及浏览器如何解释它们。
似乎我们不应该将重定向返回到异步请求,因为它们会导致问题中方法1的问题。
相反,人们一直在建议以下之一:
Ok/200
,其中包含一些特定标题,指示前端必须进行重定向Status(xyz)
前端代码将理解并解释为重定向到某个路由的请求。 选择适当的HTTP代码是另一个主题,从上面的两个选项中,我们有三个选择:
200
或自定义2xx
代码,解释为成功并在承诺中处理3xx
自定义代码可能看似合适,因为我们要求重定向401
或自定义4xx
代码。从技术上讲,传入的异步请求是未经授权的(401),因此应该是error
级响应。关键部分是处理响应代码似乎必须在问题的方法2的前端。
我倾向于默认的401