4

我正在编写一个 Play 应用程序,我需要另一个 Web 应用程序来处理身份验证。因此,当用户登录到其他 Web 应用程序时,它也应该登录到 Play 应用程序。

为了在 Play 中实现安全性,我使用了 Play Framework 文档中的说明:http ://www.playframework.com/documentation/2.0.1/ScalaSecurity

我关于如何进行外部身份验证的想法是让其他应用程序执行 ajax 调用以登录 Play 应用程序,因为我认为这会为用户编写会话 cookie。但这不起作用。我仍然需要手动登录 Play 应用程序。

这是我的控制器:

  val loginForm = Form(
    tuple(
      "username" -> nonEmptyText,
      "password" -> nonEmptyText) verifying("Invalid email or password!", result => result match {
      case (email, password) => Admin.authenticate(email, password)
    }))

    def jsLogin = Action {
        implicit request => {
            loginForm.bindFromRequest.fold(
                formWithErrors => BadRequest(toJson("Unauthorized!")),
                user => {
                    Ok(toJson("Ok")).withHeaders(
                       ACCESS_CONTROL_ALLOW_ORIGIN -> "*",
                       ACCESS_CONTROL_ALLOW_METHODS -> "POST",
                       ACCESS_CONTROL_MAX_AGE -> "300",
                       ACCESS_CONTROL_EXPOSE_HEADERS -> "Origin, X-Requested-With, Content-Type, Accept"
              ).withSession("email" -> user._1)
            })
        }
    }

这是我用来测试的代码:

$.ajax({
   type: "POST",
   url: "http://localhost:9000/jsLogin",
   data: {
       username: "username",
       password: "password"
   }
})

调试后,我知道 jsLogin 方法可以正常工作,并且确实可以登录用户,并且对 ajax 方法的响应也可以。但是当我尝试访问我的播放应用程序时,它仍然要求我手动登录。

是否有一些非 kludgy 方式让用户从外部登录?

4

2 回答 2

1

好的,我让它工作了。我注意到调用返回的 Set-Cookie 标头被认为是不安全的。为了解决这个问题,我必须正确获取 CORS 标头并发送凭据。所以这是我的新查询(出于调试原因,使用 XmlHttpRequest 而不是 jQuery 的 ajax,也应该与 ajax 一起使用)。

var xmlhttp = new XMLHttpRequest();
var url = "http://localhost:9000/jsLogin";
var params = "username=username&password=password";
xmlhttp.open("POST", url, true);
xmlhttp.withCredentials = true;
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(params);

这是播放控制器

def jsLogin = Action {
  implicit request => {
    loginForm.bindFromRequest.fold(
      formWithErrors => BadRequest(toJson("Unauthorized!")),
      user => Ok(toJson("Ok")).withHeaders(
            ACCESS_CONTROL_ALLOW_ORIGIN -> "http://sending.host.url",
            ACCESS_CONTROL_ALLOW_METHODS -> "POST",
            ACCESS_CONTROL_ALLOW_CREDENTIALS -> "true",
            ACCESS_CONTROL_ALLOW_HEADERS -> "Origin, X-Requested-With, Content-Type, Accept").withSession("email" -> user._1)
      })
  }
}

因此,解决方法是在客户端和服务器端设置“withCredentials = true”,正确设置 CORS 标头。

于 2013-07-10T06:09:31.540 回答
0

那么您想通过使用 Play 的会话 cookie 来处理安全问题吗?您是否在 AJAX 请求之后检查过 cookie 是否确实存在?“另一个”应用程序是否在同一个域上?如果否,则该 cookie 不会被其他应用程序使用。

顺便说一句,James Ward的博客文章中描述了一种更好的处理方法。

于 2013-07-02T09:28:14.593 回答