2013-07-02 40 views
4

我正在編寫一個Play應用程序,我需要將身份驗證也由另一個Web應用程序處理。所以,當用戶登錄到其他Web應用程序時,它也應該登錄到Play應用程序。在Play 2.1中使用ajax進行身份驗證

爲了實現在播放安全我用的播放框架文檔中的說明: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方法。但是當我嘗試訪問我的播放應用程序時,它仍然要求我手動登錄。

是否有一些非外掛方式讓用戶從外部登錄?

回答

0

所以你想通過使用Play的會話cookie來處理安全性?您是否檢查過Cookie後實際上是否存在AJAX請求?是同一個域名上的「其他」應用嗎?如果不是,該cookie將不會被其他應用使用。

順便提一下,James Ward描述了一種更好的處理方法in a blog post

+0

其實,我認爲我的問題是跨域cookies。我的Play應用程序在本地主機上運行,​​另一個帶有ajax登錄的Web應用程序在0.0.0.0上運行。這是在這個帖子上更多的討論:http://stackoverflow.com/questions/3342140/cross-domain-cookies我仍然需要測試在同一個域上運行這個,但如果它的工作,我會更新帖子。 – Klaus

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 =真正的」有CORS標頭設置正確。

+0

「.withCredentials = true;」幫助過我 – mulya