(refs #245)Add full name attribute for LDAP authentication.

This commit is contained in:
takezoe
2014-01-25 05:07:32 +09:00
parent 94bd1c6a93
commit 5a1f541e13
5 changed files with 65 additions and 48 deletions

View File

@@ -18,51 +18,49 @@ object LDAPUtil {
/**
* Try authentication by LDAP using given configuration.
* Returns Right(mailAddress) if authentication is successful, otherwise Left(errorMessage).
* Returns Right(LDAPUserInfo) if authentication is successful, otherwise Left(errorMessage).
*/
def authenticate(ldapSettings: Ldap, userName: String, password: String): Either[String, String] = {
def authenticate(ldapSettings: Ldap, userName: String, password: String): Either[String, LDAPUserInfo] = {
bind(
ldapSettings.host,
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
ldapSettings.bindDN.getOrElse(""),
ldapSettings.bindPassword.getOrElse(""),
ldapSettings.tls.getOrElse(false),
ldapSettings.keystore.getOrElse("")
) match {
case Some(conn) => {
withConnection(conn) { conn =>
findUser(conn, userName, ldapSettings.baseDN, ldapSettings.userNameAttribute) match {
case Some(userDN) => userAuthentication(ldapSettings, userDN, password)
case None => Left("User does not exist.")
}
}
host = ldapSettings.host,
port = ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
dn = ldapSettings.bindDN.getOrElse(""),
password = ldapSettings.bindPassword.getOrElse(""),
tls = ldapSettings.tls.getOrElse(false),
keystore = ldapSettings.keystore.getOrElse(""),
error = "System LDAP authentication failed."
){ conn =>
findUser(conn, userName, ldapSettings.baseDN, ldapSettings.userNameAttribute) match {
case Some(userDN) => userAuthentication(ldapSettings, userDN, userName, password)
case None => Left("User does not exist.")
}
case None => Left("System LDAP authentication failed.")
}
}
private def userAuthentication(ldapSettings: Ldap, userDN: String, password: String): Either[String, String] = {
private def userAuthentication(ldapSettings: Ldap, userDN: String, userName: String, password: String): Either[String, LDAPUserInfo] = {
bind(
ldapSettings.host,
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
userDN,
password,
ldapSettings.tls.getOrElse(false),
ldapSettings.keystore.getOrElse("")
) match {
case Some(conn) => {
withConnection(conn) { conn =>
findMailAddress(conn, userDN, ldapSettings.mailAttribute) match {
case Some(mailAddress) => Right(mailAddress)
case None => Left("Can't find mail address.")
}
}
host = ldapSettings.host,
port = ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
dn = userDN,
password = password,
tls = ldapSettings.tls.getOrElse(false),
keystore = ldapSettings.keystore.getOrElse(""),
error = "User LDAP Authentication Failed."
){ conn =>
findMailAddress(conn, userDN, ldapSettings.mailAttribute) match {
case Some(mailAddress) => Right(LDAPUserInfo(
userName = userName,
fullName = ldapSettings.fullNameAttribute.flatMap { fullNameAttribute =>
findFullName(conn, userDN, fullNameAttribute)
}.getOrElse(userName),
mailAddress = mailAddress))
case None => Left("Can't find mail address.")
}
case None => Left("User LDAP Authentication Failed.")
}
}
private def bind(host: String, port: Int, dn: String, password: String, tls: Boolean, keystore: String): Option[LDAPConnection] = {
private def bind[A](host: String, port: Int, dn: String, password: String, tls: Boolean, keystore: String, error: String)
(f: LDAPConnection => Either[String, A]): Either[String, A] = {
if (tls) {
// Dynamically set Sun as the security provider
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
@@ -87,7 +85,9 @@ object LDAPUtil {
// Bind to the server
conn.bind(LDAP_VERSION, dn, password.getBytes)
Some(conn)
// Execute a given function and returns a its result
f(conn)
} catch {
case e: Exception => {
// Provide more information if something goes wrong
@@ -96,20 +96,15 @@ object LDAPUtil {
if (conn.isConnected) {
conn.disconnect()
}
None
// Returns an error message
Left(error)
}
}
}
private def withConnection[T](conn: LDAPConnection)(f: LDAPConnection => T): T = {
try {
f(conn)
} finally {
conn.disconnect()
}
}
/**
* Search a specified user and returns userDN if exists.
*/
private def findUser(conn: LDAPConnection, userName: String, baseDN: String, userNameAttribute: String): Option[String] = {
@tailrec
def getEntries(results: LDAPSearchResults, entries: List[Option[LDAPEntry]] = Nil): List[LDAPEntry] = {
@@ -134,4 +129,14 @@ object LDAPUtil {
Option(results.next.getAttribute(mailAttribute)).map(_.getStringValue)
} else None
}
private def findFullName(conn: LDAPConnection, userDN: String, nameAttribute: String): Option[String] =
defining(conn.search(userDN, LDAPConnection.SCOPE_BASE, null, Array[String](nameAttribute), false)){ results =>
if(results.hasMore) {
Option(results.next.getAttribute(nameAttribute)).map(_.getStringValue)
} else None
}
case class LDAPUserInfo(userName: String, fullName: String, mailAddress: String)
}