首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用play框架、silhouette和satellizer登录Facebook

无法使用play框架、silhouette和satellizer登录Facebook
EN

Stack Overflow用户
提问于 2017-03-29 03:32:38
回答 1查看 238关注 0票数 2

今天早上,当我意识到facebook登录在我的应用程序中不再起作用时,我还挺好的。正如我所提到的,我使用的是带有silhouette 2.0版的play框架-RC1。

这就是问题:

代码语言:javascript
复制
[Silhouette][facebook] Cannot build OAuth2Info because of invalid response format  : {"access_token":"EAAE2YyQkAUUBANAfoUfhdG8jrRfJnhrgZCaZB5FsZAO1G5Jq0ITTfZA6coj4g0HuUC48JToHCnZCFx8r9Q3JZCulzt6SaEcRqKrxNealsBldH4dpzJpK4oeblZAmxjq9Rjzl2rO3IKPUwllWAv5vEz33cGc4XeqLSgZD","token_type":"bearer","expires_in":5183717}

问题是身份验证的Json响应没有像OAuth2Info期望的那样具有正确的格式,这很奇怪,因为我们从来没有接触过身份验证机制,我担心这可能是一个库版本问题,并且更新轮廓现在不是一个选项...是否有人遇到了这个问题并找到了解决方案?请帮我处理这些家伙。非常感谢。

EN

回答 1

Stack Overflow用户

发布于 2017-03-30 04:09:04

我们必须创建一个自定义的FacebookProvider实现,以便处理新的facebook的答案。就是这里

代码语言:javascript
复制
    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
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43078349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档