2017-03-28 55 views
1

今天早上我做得很好,當時我意識到facebook登錄在我的應用程序中不再有效。正如我所提到的,我正在使用剪影版本2.0-RC1的遊戲框架。不能用Facebook登錄玩框架,剪影和衛星

這就是問題所在:

[Silhouette][facebook] Cannot build OAuth2Info because of invalid response format : {"access_token":"EAAE2YyQkAUUBANAfoUfhdG8jrRfJnhrgZCaZB5FsZAO1G5Jq0ITTfZA6coj4g0HuUC48JToHCnZCFx8r9Q3JZCulzt6SaEcRqKrxNealsBldH4dpzJpK4oeblZAmxjq9Rjzl2rO3IKPUwllWAv5vEz33cGc4XeqLSgZD","token_type":"bearer","expires_in":5183717} 

的問題是,對於認證JSON響應不正確的格式爲OAuth2Info預期,這是奇怪的,因爲我們從來沒有接觸認證mecanism和我m擔心,因爲它可能是一個庫版本問題,更新剪影現在不是一個選項...是否有人遇到這個問題,並找到解決方案?請幫助我與這個傢伙...非常感謝。

回答

0

我們必須創建FacebookProvider的自定義實現以處理新的Facebook答案。這是

import com.mohiva.play.silhouette.api.LoginInfo 
    import com.mohiva.play.silhouette.api.exceptions.AuthenticationException 
    import com.mohiva.play.silhouette.api.util.HTTPLayer 
    import com.mohiva.play.silhouette.impl.exceptions.ProfileRetrievalException 
    import com.mohiva.play.silhouette.impl.providers.OAuth2Provider._ 
    import com.mohiva.play.silhouette.impl.providers._ 
    import com.mohiva.play.silhouette.impl.providers.oauth2.{FacebookProfileBuilder, FacebookProvider} 
    import com.mohiva.play.silhouette.impl.providers.oauth2.FacebookProvider._ 
    import play.api.libs.concurrent.Execution.Implicits._ 
    import play.api.libs.json.{ JsObject, JsValue } 
    import play.api.libs.ws.WSResponse 
    import play.api.libs.json._ 

    import scala.concurrent.Future 
    import scala.util.{ Failure, Success, Try } 

    /** 
    * A Facebook OAuth2 Provider. 
    * 
    * @param httpLayer The HTTP layer implementation. 
    * @param stateProvider The state provider implementation. 
    * @param settings The provider settings. 
    * 
    * @see https://developers.facebook.com/tools/explorer 
    * @see https://developers.facebook.com/docs/graph-api/reference/user 
    * @see https://developers.facebook.com/docs/facebook-login/access-tokens 
    */ 
    abstract class FacebookProvider(httpLayer: HTTPLayer, stateProvider: OAuth2StateProvider, settings: OAuth2Settings) 
     extends OAuth2Provider(httpLayer, stateProvider, settings) { 

     /** 
     * The content type to parse a profile from. 
     */ 
     type Content = JsValue 

     /** 
     * Gets the provider ID. 
     * 
     * @return The provider ID. 
     */ 
     val id = ID 

     /** 
     * Defines the URLs that are needed to retrieve the profile data. 
     */ 
     protected val urls = Map("api" -> API) 

     /** 
     * Builds the social profile. 
     * 
     * @param authInfo The auth info received from the provider. 
     * @return On success the build social profile, otherwise a failure. 
     */ 
     protected def buildProfile(authInfo: OAuth2Info): Future[Profile] = { 
     httpLayer.url(urls("api").format(authInfo.accessToken)).get().flatMap { response => 
      val json = response.json 
      (json \ "error").asOpt[JsObject] match { 
      case Some(error) => 
       val errorMsg = (error \ "message").as[String] 
       val errorType = (error \ "type").as[String] 
       val errorCode = (error \ "code").as[Int] 

       throw new ProfileRetrievalException(SpecifiedProfileError.format(id, errorMsg, errorType, errorCode)) 
      case _ => profileParser.parse(json) 
      } 
     } 
     } 

     /** 
     * Builds the OAuth2 info from response. 
     * 
     * @param response The response from the provider. 
     * @return The OAuth2 info on success, otherwise a failure. 
     */ 
     override def buildInfo(response: WSResponse): Try[OAuth2Info] = { 
     val responseJson = Json.parse(response.body) 
     responseJson.validate[OAuth2Info].asEither.fold(
      error => Failure(new AuthenticationException(InvalidInfoFormat.format(id, error))), 
      info => Success(info) 
     ) 
     } 
    } 

    /** 
    * The profile parser for the common social profile. 
    */ 
    class FacebookProfileParser extends SocialProfileParser[JsValue, CommonSocialProfile] { 

     /** 
     * Parses the social profile. 
     * 
     * @param json The content returned from the provider. 
     * @return The social profile from given result. 
     */ 
     def parse(json: JsValue) = Future.successful { 
     val userID = (json \ "id").as[String] 
     val firstName = (json \ "first_name").asOpt[String] 
     val lastName = (json \ "last_name").asOpt[String] 
     val fullName = (json \ "name").asOpt[String] 
     val avatarURL = (json \ "picture" \ "data" \ "url").asOpt[String] 
     val email = (json \ "email").asOpt[String] 

     CommonSocialProfile(
      loginInfo = LoginInfo(ID, userID), 
      firstName = firstName, 
      lastName = lastName, 
      fullName = fullName, 
      avatarURL = avatarURL, 
      email = email) 
     } 
    } 

    /** 
    * The profile builder for the common social profile. 
    */ 
    trait FacebookProfileBuilder extends CommonSocialProfileBuilder { 
     self: FacebookProvider => 

     /** 
     * The profile parser implementation. 
     */ 
     val profileParser = new FacebookProfileParser 
    } 

    /** 
    * The companion object. 
    */ 
    object FacebookWesuraProvider { 

     /** 
     * The error messages. 
     */ 
     val SpecifiedProfileError = "[Silhouette][%s] Error retrieving profile information. Error message: %s, type: %s, code: %s" 

     /** 
     * The Facebook constants. 
     */ 
     val ID = "facebook" 
     val API = "https://graph.facebook.com/me?fields=name,first_name,last_name,picture,email&return_ssl_resources=1&access_token=%s" 

     /** 
     * Creates an instance of the provider. 
     * 
     * @param httpLayer The HTTP layer implementation. 
     * @param stateProvider The state provider implementation. 
     * @param settings The provider settings. 
     * @return An instance of this provider. 
     */ 
     def apply(httpLayer: HTTPL 

ayer, stateProvider: OAuth2StateProvider, settings: OAuth2Settings) = { 
    new FacebookProvider(httpLayer, stateProvider, settings) with FacebookProfileBuilder 
    } 
}