Статьи

Включение LDAP с приложением Play 2.x (Scala)

Для людей, которые спешат, вот код и шаги .

В продолжении  Play 2.x (Scala) это соперник Spring MVC? — Введение. В этом блоге я расширяю свой предыдущий блог « Включение авторизации» в приложение Play 2.x (Scala) для интеграции с LDAP вместо базы данных.

Опять же, могут быть лучшие способы сделать это, но сейчас нет четкой документации. При быстром поиске в Google отобразится ссылка на группу Google,  а также ссылка и код Github . Все они оказали мне небольшую помощь. Поэтому я сделал 1-й шаг и поставил один из них. Я использовал Unboundid LDAP SDK «s InMemoryDirectoryServer .

В качестве первого шага нам нужно добавить следующую зависимость в Build.scala ,

"com.unboundid" % "unboundid-ldapsdk" % "2.3.1",

Затем мы реализуем в памяти вспомогательный класс LDAP LdapUtil.scala, как показано ниже:

  def start(): InMemoryDirectoryServer = {
    val config = new InMemoryDirectoryServerConfig("dc=org");
    val listenerConfig = new InMemoryListenerConfig("test", null, 12345, null, null, null);
    config.setListenerConfigs(listenerConfig);
    config.setSchema(null); // do not check (attribute) schema
    val server = new InMemoryDirectoryServer(config);
    server.startListening();
...
    server.add("dn: [email protected],dc=staticsecurity,dc=geomajas,dc=org", "objectClass: person", "locale: nl_BE",
      "sn: NormalUser", "givenName: Joe", "memberOf: cn=testgroup,dc=roles,dc=geomajas,dc=org", "userPassword: password");
    server.add("dn: [email protected],dc=staticsecurity,dc=geomajas,dc=org", "objectClass: person", "locale: nl_BE",
      "sn: Administrator", "givenName: Cindy", "memberOf: cn=testgroup,dc=roles,dc=geomajas,dc=org", "userPassword: password");
 
    server
  }
 
  def authenticate(email: String, password: String): Option[Account] = {
    val server = start
 
    val conn = server.getConnection();
    val entry = conn.getEntry("cn=" + email + ",dc=staticsecurity,dc=geomajas,dc=org");
 
    val permission = entry.getAttributeValue("sn").toString
    val retPass = entry.getAttributeValue("userPassword")
    server.shutDown(true)
 
    if (retPass.equals(password)) {
      println("password valid")
      val account = new Account(email, password, permission)
      toOption(account)
    } else {
      None
    }
  }
 
  def findByEmail(email: String): Option[Account] = {
    val server = start
    val conn = server.getConnection();
    val entry = conn.getEntry("cn=" + email + ",dc=staticsecurity,dc=geomajas,dc=org");
 
    val permission = entry.getAttributeValue("sn").toString
    val retPass = entry.getAttributeValue("userPassword")
    server.shutDown(true)
 
    val account = new Account(email, retPass, permission)
    toOption(account)
  }

Если вы заметили, что обычные права пользователя — это email: = [email protected], pwd: = пароль, а права администратора — это email: = [email protected], pwd: = пароль. Как и в моем предыдущем блоге, нам нужно настроить AuthConfig, как показано ниже:

trait AuthConfigImpl extends AuthConfig {
  type Id = String
  type User = Account
  type Authority = String
  val idTag = classTag[Id]
...
  def resolveUser(email: Id) = LdapUtil.findByEmail(email)
...
  def authorize(user: User, authority: Authority) = (user.permission, authority) match {
    case ("Administrator", _) => true
    case ("NormalUser", "NormalUser") => true
    case _ => false
  }
}

Форма входа выглядит как ниже, как в Application.scala ,

val loginForm = Form {
  mapping("email" -> email, "password" -> text)(LdapUtil.authenticate)(_.map(u => (u.email, "")))
    .verifying("Invalid email or password", result => result.isDefined)
}

Наконец, использование выглядит так, как показано ниже CoffeesControler.scala ,

def create = StackAction(AuthorityKey -> "Administrator") { implicit request =>
    database withSession {
      Ok(html.coffees.createForm(form, supplierSelect))
    }
  }