我一直致力于学习如何使用Play框架。据我所知,插件可用于添加其他人开发的功能。也许我应该称之为模块?我读到SercureSocial是可用于身份验证的最佳模块之一。但是文档并没有让我到处都是。有人可以帮我理解如何将master-snapshot添加到我现有的java项目中吗?
让我们假设我表演了 activator 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?
答案 0 :(得分:2)
过去几天我一直在经历这个问题。在这个时间点,我建议你忽略文档。它不是最新的(文档是2,但是游戏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。
答案 1 :(得分:2)
有人可以帮助我了解如何将主快照添加到我的 现有的java项目?
我只尝试使用Scala版本而不是Java,但我希望以下内容有所帮助。
在build.sbt文件中,将以下行添加到libraryDependencies:
"ws.securesocial" %% "securesocial" % "master-SNAPSHOT"
没有Build.scala文件,但我看到有一个build.sbt文件。做 我将此块添加到build.sbt文件中?
您需要添加到build.sbt的唯一其他事项是Sonatype OSS Snapshots存储库URL:
resolvers +=
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
复制上面的块之后,我在中创建了ply.plugins文件 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 强> https://github.com/jaliss/securesocial/blob/master/samples/scala/demo/conf/securesocial.conf
您需要配置smtp邮件设置和任何securesocial配置。
InMemoryUserService
/**
* 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 强>
的Scala https://github.com/jaliss/securesocial/blob/master/samples/scala/demo/app/Global.scala
爪哇 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>
}
答案 2 :(得分:0)
嗯...... libraryDependencies
是SettingKey[ Seq[ ModuleId ] ]
。
现在,SettingKey[ Seq[ ModuleId ] ]
可以被视为类似于Seq
或List
的内容,它提供了类似的功能。
所以...你可以添加新的依赖项,就像你将添加到任何其他Seq
或List
一样。
libraryDependencies += "ws.securesocial" %% "securesocial" % "2.1.4"