【问题标题】:How to install SecureSocial on Play Frame work 2.3.8?如何在 Play Frame work 2.3.8 上安装 SecureSocial?
【发布时间】:2015-05-20 08:07:21
【问题描述】:

我一直在努力学习如何使用 Play 框架。据我了解,插件可用于添加其他人开发的功能。也许我应该称它为模块?我读到 SercureSocial 是可用于身份验证的最佳模块之一。但是文档并没有真正让我到任何地方。有人可以帮助我了解如何将主快照添加到我现有的 java 项目中吗?

假设我执行了 激活器 new my-first-app play-scala 激活剂日食 我将项目导入到eclipse中

下一步是尝试按照以下网址的指示进行操作

http://securesocial.ws/guide/installation.html

读完我还是迷路了。

没有 Build.scala 文件,但我看到有一个 build.sbt 文件。我是否将此块添加到 build.sbt 文件中?

object ApplicationBuild extends Build {
val appName         = "my-first-app"
val appVersion      = "1.0-SNAPSHOT"

val appDependencies = Seq(
    "ws.securesocial" %% "securesocial" % "master-SNAPSHOT"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
    resolvers += Resolver.sonatypeRepo("releases")
)

val main = play.Project(appName, appVersion, appDependencies).settings(
  resolvers += Resolver.sonatypeRepo("snapshots")
)

复制上面的块后,我在 conf 文件夹中创建了 ply.plugins 文件。然后我将所有插件复制到文件中并保存

1500:com.typesafe.plugin.CommonsMailerPlugin
9994:securesocial.core.DefaultAuthenticatorStore
9995:securesocial.core.DefaultIdGenerator
9996:securesocial.core.providers.utils.DefaultPasswordValidator
9997:securesocial.controllers.DefaultTemplatesPlugin
9998:your.user.Service.Implementation <-- Important: You need to change this
9999:securesocial.core.providers.utils.BCryptPasswordHasher
10000:securesocial.core.providers.TwitterProvider
10001:securesocial.core.providers.FacebookProvider
10002:securesocial.core.providers.GoogleProvider
10003:securesocial.core.providers.LinkedInProvider
10004:securesocial.core.providers.UsernamePasswordProvider
10005:securesocial.core.providers.GitHubProvider
10006:securesocial.core.providers.FoursquareProvider
10007:securesocial.core.providers.XingProvider
10008:securesocial.core.providers.VkProvider
10009:securesocial.core.providers.InstagramProvider

接下来,我将所有路由复制到路由文件中

# Login page
GET     /login                      securesocial.controllers.LoginPage.login
GET     /logout                     securesocial.controllers.LoginPage.logout

# User Registration and password handling 
GET     /signup                     securesocial.controllers.Registration.startSignUp
POST    /signup                     securesocial.controllers.Registration.handleStartSignUp
GET     /signup/:token              securesocial.controllers.Registration.signUp(token)
POST    /signup/:token              securesocial.controllers.Registration.handleSignUp(token)
GET     /reset                      securesocial.controllers.Registration.startResetPassword
POST    /reset                      securesocial.controllers.Registration.handleStartResetPassword
GET     /reset/:token               securesocial.controllers.Registration.resetPassword(token)
POST    /reset/:token               securesocial.controllers.Registration.handleResetPassword(token)
GET     /password                   securesocial.controllers.PasswordChange.page
POST    /password                   securesocial.controllers.PasswordChange.handlePasswordChange

# Providers entry points
GET     /authenticate/:provider     securesocial.controllers.ProviderController.authenticate(provider)
POST    /authenticate/:provider     securesocial.controllers.ProviderController.authenticateByPost(provider)
GET     /not-authorized             securesocial.controllers.ProviderController.notAuthorized

然后我尝试运行该项目并收到以下错误

[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  ::          UNRESOLVED DEPENDENCIES         ::
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  :: ws.securesocial#securesocial;2.1.4: not found
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn]  Note: Some unresolved dependencies have extra attributes.  Check that these dependencies exist with the requested attributes.
[warn]          ws.securesocial:securesocial:2.1.4 (scalaVersion=2.10, sbtVersion=0.13)
[warn]
sbt.ResolveException: unresolved dependency: ws.securesocial#securesocial;2.1.4:not found
    at sbt.IvyActions$.sbt$IvyActions$$resolve(IvyActions.scala:217)
    at sbt.IvyActions$$anonfun$update$1.apply(IvyActions.scala:126)
    at sbt.IvyActions$$anonfun$update$1.apply(IvyActions.scala:125)
    at sbt.IvySbt$Module$$anonfun$withModule$1.apply(Ivy.scala:115)
    at sbt.IvySbt$Module$$anonfun$withModule$1.apply(Ivy.scala:115)
    at sbt.IvySbt$$anonfun$withIvy$1.apply(Ivy.scala:103)
    at sbt.IvySbt.sbt$IvySbt$$action$1(Ivy.scala:48)
    at sbt.IvySbt$$anon$3.call(Ivy.scala:57)
    at xsbt.boot.Locks$GlobalLock.withChannel$1(Locks.scala:93)
    at xsbt.boot.Locks$GlobalLock.xsbt$boot$Locks$GlobalLock$$withChannelRetries$1(Locks.scala:78)
    at xsbt.boot.Locks$GlobalLock$$anonfun$withFileLock$1.apply(Locks.scala:97)
    at xsbt.boot.Using$.withResource(Using.scala:10)
    at xsbt.boot.Using$.apply(Using.scala:9)
    at xsbt.boot.Locks$GlobalLock.ignoringDeadlockAvoided(Locks.scala:58)
    at xsbt.boot.Locks$GlobalLock.withLock(Locks.scala:48)
    at xsbt.boot.Locks$.apply0(Locks.scala:31)
    at xsbt.boot.Locks$.apply(Locks.scala:28)
    at sbt.IvySbt.withDefaultLogger(Ivy.scala:57)
    at sbt.IvySbt.withIvy(Ivy.scala:98)
    at sbt.IvySbt.withIvy(Ivy.scala:94)
    at sbt.IvySbt$Module.withModule(Ivy.scala:115)
    at sbt.IvyActions$.update(IvyActions.scala:125)
    at sbt.Classpaths$$anonfun$sbt$Classpaths$$work$1$1.apply(Defaults.scala:1223)
    at sbt.Classpaths$$anonfun$sbt$Classpaths$$work$1$1.apply(Defaults.scala:1221)
    at sbt.Classpaths$$anonfun$doWork$1$1$$anonfun$74.apply(Defaults.scala:1244)
    at sbt.Classpaths$$anonfun$doWork$1$1$$anonfun$74.apply(Defaults.scala:1242)
    at sbt.Tracked$$anonfun$lastOutput$1.apply(Tracked.scala:35)
    at sbt.Classpaths$$anonfun$doWork$1$1.apply(Defaults.scala:1246)
    at sbt.Classpaths$$anonfun$doWork$1$1.apply(Defaults.scala:1241)
    at sbt.Tracked$$anonfun$inputChanged$1.apply(Tracked.scala:45)
    at sbt.Classpaths$.cachedUpdate(Defaults.scala:1249)
    at sbt.Classpaths$$anonfun$updateTask$1.apply(Defaults.scala:1214)
    at sbt.Classpaths$$anonfun$updateTask$1.apply(Defaults.scala:1192)
    at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
    at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
    at sbt.std.Transform$$anon$4.work(System.scala:64)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
    at sbt.Execute.work(Execute.scala:244)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
    at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
[error] (*:update) sbt.ResolveException: unresolved dependency: ws.securesocial#securesocial;2.1.4: not found
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?

【问题讨论】:

  • 您阅读安装指南了吗? securesocial.ws/guide/installation.html
  • 是的。我是否必须将 "ws.securesocial" %% "securesocial" % "2.1.4" 行更改为其他内容,在哪里添加?它是否添加到 build.sbt 中?是否在块中添加: libraryDependencies ++= Seq( javaJdbc, javaEbean, cache, javaWs )
  • 我添加了有关我的问题的更多详细信息

标签: java scala playframework-2.0 playframework-2.3 securesocial


【解决方案1】:

过去几天我自己也在经历这个。此时,我建议您忽略文档。它不是最新的(文档适用于 2,但 play 2.3.x 似乎需要 3)。像 play.plugins 这样的东西会让你走错路。

将 M3 安装到 2.3.X 上的安装过程很艰难,但我确实认为我可以在 Java 中使用它。这些资源对我很有帮助。从示例中提取诸如 .sbt 设置之类的内容。

首先,阅读high level overview。其次,clone the sample 并让它运行。这 SO on running it 很有帮助。第三,将示例中的代码迁移到本地树中。一旦你开始这样做,你可能会看到没有样式。有关如何显示 css/js 的信息,请参阅 this

【讨论】:

    【解决方案2】:

    谁能帮助我了解如何将主快照添加到我的 现有的java项目?

    我只尝试了 Scala 版本而不是 Java,但我希望以下内容能有所帮助。

    在您的 build.sbt 文件中,将以下行添加到您的 libraryDependencies:

    "ws.securesocial" %% "securesocial" % "master-SNAPSHOT"
    

    没有 Build.scala 文件,但我看到有一个 build.sbt 文件。做 我将此块添加到 build.sbt 文件中?

    您需要添加到 build.sbt 的唯一其他内容是 Sonatype OSS 快照存储库 URL:

    resolvers += 
      "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
    

    复制上面的块后,我在 conf 文件夹。然后我将所有插件复制到文件中并保存

    您需要在 play.plugins 文件中配置的唯一插件是 CommonsMailerPlugin:

    1500:com.typesafe.plugin.CommonsMailerPlugin
    

    接下来,我将所有路由复制到路由文件中

    请尝试以下示例,而不是基于旧版本的securesocal:

    # your secure page
    GET        /                        @controllers.Application.index
    # securesocial routes
    GET        /login                   @securesocial.controllers.LoginPage.login
    GET        /logout                  @securesocial.controllers.LoginPage.logout
    ->         /auth                    securesocial.Routes
    

    为了让一个工作示例运行,您需要以下内容:

    • securesocial.conf 文件在 conf 文件夹中创建并包含在您的 application.conf 文件中,以便被拾取
    • InMemoryUserService.scala
    • Global.scala
    • 您的安全应用程序控制器
    • 您的安全页面

    securesocial.conf https://github.com/jaliss/securesocial/blob/master/samples/scala/demo/conf/securesocial.conf

    您需要配置您的 smtp 邮件设置和任何安全社交配置。

    InMemoryUserService

    斯卡拉 https://github.com/jaliss/securesocial/blob/master/samples/scala/demo/app/service/InMemoryUserService.scala

    Java https://github.com/jaliss/securesocial/blob/master/samples/java/demo/app/service/InMemoryUserService.java

    /**
     * Copyright 2012 Jorge Aliss (jaliss at gmail dot com) - twitter: @jaliss
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    package service
    
    import play.api.Logger
    import securesocial.core._
    import securesocial.core.providers.{ UsernamePasswordProvider, MailToken }
    import scala.concurrent.Future
    import securesocial.core.services.{ UserService, SaveMode }
    
    /**
     * A Sample In Memory user service in Scala
     *
     * IMPORTANT: This is just a sample and not suitable for a production environment since
     * it stores everything in memory.
     */
    class InMemoryUserService extends UserService[DemoUser] {
      val logger = Logger("application.controllers.InMemoryUserService")
    
      //
      var users = Map[(String, String), DemoUser]()
      //private var identities = Map[String, BasicProfile]()
      private var tokens = Map[String, MailToken]()
    
      def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
        if (logger.isDebugEnabled) {
          logger.debug("users = %s".format(users))
        }
        val result = for (
          user <- users.values;
          basicProfile <- user.identities.find(su => su.providerId == providerId && su.userId == userId)
        ) yield {
          basicProfile
        }
        Future.successful(result.headOption)
      }
    
      def findByEmailAndProvider(email: String, providerId: String): Future[Option[BasicProfile]] = {
        if (logger.isDebugEnabled) {
          logger.debug("users = %s".format(users))
        }
        val someEmail = Some(email)
        val result = for (
          user <- users.values;
          basicProfile <- user.identities.find(su => su.providerId == providerId && su.email == someEmail)
        ) yield {
          basicProfile
        }
        Future.successful(result.headOption)
      }
    
      private def findProfile(p: BasicProfile) = {
        users.find {
          case (key, value) if value.identities.exists(su => su.providerId == p.providerId && su.userId == p.userId) => true
          case _ => false
        }
      }
    
      private def updateProfile(user: BasicProfile, entry: ((String, String), DemoUser)): Future[DemoUser] = {
        val identities = entry._2.identities
        val updatedList = identities.patch(identities.indexWhere(i => i.providerId == user.providerId && i.userId == user.userId), Seq(user), 1)
        val updatedUser = entry._2.copy(identities = updatedList)
        users = users + (entry._1 -> updatedUser)
        Future.successful(updatedUser)
      }
    
      def save(user: BasicProfile, mode: SaveMode): Future[DemoUser] = {
        mode match {
          case SaveMode.SignUp =>
            val newUser = DemoUser(user, List(user))
            users = users + ((user.providerId, user.userId) -> newUser)
            Future.successful(newUser)
          case SaveMode.LoggedIn =>
            // first see if there is a user with this BasicProfile already.
            findProfile(user) match {
              case Some(existingUser) =>
                updateProfile(user, existingUser)
    
              case None =>
                val newUser = DemoUser(user, List(user))
                users = users + ((user.providerId, user.userId) -> newUser)
                Future.successful(newUser)
            }
    
          case SaveMode.PasswordChange =>
            findProfile(user).map { entry => updateProfile(user, entry) }.getOrElse(
              // this should not happen as the profile will be there
              throw new Exception("missing profile)")
            )
        }
      }
    
      def link(current: DemoUser, to: BasicProfile): Future[DemoUser] = {
        if (current.identities.exists(i => i.providerId == to.providerId && i.userId == to.userId)) {
          Future.successful(current)
        } else {
          val added = to :: current.identities
          val updatedUser = current.copy(identities = added)
          users = users + ((current.main.providerId, current.main.userId) -> updatedUser)
          Future.successful(updatedUser)
        }
      }
    
      def saveToken(token: MailToken): Future[MailToken] = {
        Future.successful {
          tokens += (token.uuid -> token)
          token
        }
      }
    
      def findToken(token: String): Future[Option[MailToken]] = {
        Future.successful { tokens.get(token) }
      }
    
      def deleteToken(uuid: String): Future[Option[MailToken]] = {
        Future.successful {
          tokens.get(uuid) match {
            case Some(token) =>
              tokens -= uuid
              Some(token)
            case None => None
          }
        }
      }
    
      //  def deleteTokens(): Future {
      //    tokens = Map()
      //  }
    
      def deleteExpiredTokens() {
        tokens = tokens.filter(!_._2.isExpired)
      }
    
      override def updatePasswordInfo(user: DemoUser, info: PasswordInfo): Future[Option[BasicProfile]] = {
        Future.successful {
          for (
            found <- users.values.find(_ == user);
            identityWithPasswordInfo <- found.identities.find(_.providerId == UsernamePasswordProvider.UsernamePassword)
          ) yield {
            val idx = found.identities.indexOf(identityWithPasswordInfo)
            val updated = identityWithPasswordInfo.copy(passwordInfo = Some(info))
            val updatedIdentities = found.identities.patch(idx, Seq(updated), 1)
            val updatedEntry = found.copy(identities = updatedIdentities)
            users = users + ((updatedEntry.main.providerId, updatedEntry.main.userId) -> updatedEntry)
            updated
          }
        }
      }
    
      override def passwordInfoFor(user: DemoUser): Future[Option[PasswordInfo]] = {
        Future.successful {
          for (
            found <- users.values.find(u => u.main.providerId == user.main.providerId && u.main.userId == user.main.userId);
            identityWithPasswordInfo <- found.identities.find(_.providerId == UsernamePasswordProvider.UsernamePassword)
          ) yield {
            identityWithPasswordInfo.passwordInfo.get
          }
        }
      }
    }
    
    // a simple User class that can have multiple identities
    case class DemoUser(main: BasicProfile, identities: List[BasicProfile])
    

    Global.scala

    斯卡拉 https://github.com/jaliss/securesocial/blob/master/samples/scala/demo/app/Global.scala

    Java https://github.com/jaliss/securesocial/blob/master/samples/java/demo/app/Global.java

    /**
     * Copyright 2014 Jorge Aliss (jaliss at gmail dot com) - twitter: @jaliss
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    import controllers.CustomRoutesService
    import java.lang.reflect.Constructor
    import securesocial.core.RuntimeEnvironment
    import service.{ DemoUser, MyEventListener, InMemoryUserService }
    
    object Global extends play.api.GlobalSettings {
    
      /**
       * The runtime environment for this sample app.
       */
      object MyRuntimeEnvironment extends RuntimeEnvironment.Default[DemoUser] {
        override implicit val executionContext = play.api.libs.concurrent.Execution.defaultContext
        override lazy val routes = new CustomRoutesService()
        override lazy val userService: InMemoryUserService = new InMemoryUserService()
        override lazy val eventListeners = List(new MyEventListener())
      }
    
      /**
       * An implementation that checks if the controller expects a RuntimeEnvironment and
       * passes the instance to it if required.
       *
       * This can be replaced by any DI framework to inject it differently.
       *
       * @param controllerClass
       * @tparam A
       * @return
       */
      override def getControllerInstance[A](controllerClass: Class[A]): A = {
        val instance = controllerClass.getConstructors.find { c =>
          val params = c.getParameterTypes
          params.length == 1 && params(0) == classOf[RuntimeEnvironment[DemoUser]]
        }.map {
          _.asInstanceOf[Constructor[A]].newInstance(MyRuntimeEnvironment)
        }
        instance.getOrElse(super.getControllerInstance(controllerClass))
      }
    }
    

    安全应用程序控制器

    package controllers
    
    import play.api._
    import play.api.mvc._
    
    import securesocial.core._
    import service.DemoUser
    
    class Application(override implicit val env: RuntimeEnvironment[DemoUser]) extends SecureSocial[DemoUser] {
    
      def index = SecuredAction { implicit request =>
        Ok(views.html.index(request.user.main))
      }
    }
    

    安全页面 - index.scala.html

    @(user: securesocial.core.BasicProfile)(implicit request: RequestHeader, env: securesocial.core.RuntimeEnvironment[service.DemoUser])
    
    @main("Secure Page") {
        <h2>User Id:@user.userId</h2>
        <hr>
        <a class="btn" href="@securesocial.controllers.routes.LoginPage.logout()">Logout</a>
    }
    

    【讨论】:

    • 如何配置播放插件?
    • 您是指 play.plugins 文件中的内容还是如何配置安全社交? conf/play.plugins 文件中唯一需要的行是:1500:com.typesafe.plugin.CommonsMailerPlugin。 Secure social 提供了一个默认的securesocial.conf 文件供您编辑。有很多选项可供选择
    • 你说The only plugin you need configured in the play.plugins file is the CommonsMailerPlugin:,但我不知道如何配置。
    • 我在 application.conf 文件中配置了 smtp 设置,并在 build.sbt 文件中添加了库依赖项。您可以查看播放开始应用程序模板,其中包含如何配置插件的示例:typesafe.com/activator/template/PlayStartApp。另请查看此 stackoverflow 页面,因为根据所使用的 Play 版本,该软件包似乎存在一些问题:stackoverflow.com/a/27132985/349842
    【解决方案3】:

    嗯...libraryDependenciesSettingKey[ Seq[ ModuleId ] ]

    现在,SettingKey[ Seq[ ModuleId ] ] 可以看作类似于SeqList,它提供了类似的功能。

    所以...您可以将新的依赖项添加到它,就像您将添加到任何其他 SeqList 一样。

    libraryDependencies += "ws.securesocial" %% "securesocial" % "2.1.4"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-15
      • 2013-11-26
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多