mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-10-30 10:06:07 +01:00
(refs #78)Implementing LDAP authentication.
This commit is contained in:
@@ -36,6 +36,7 @@ object MyBuild extends Build {
|
|||||||
"org.pegdown" % "pegdown" % "1.3.0",
|
"org.pegdown" % "pegdown" % "1.3.0",
|
||||||
"org.apache.commons" % "commons-compress" % "1.5",
|
"org.apache.commons" % "commons-compress" % "1.5",
|
||||||
"com.typesafe.slick" %% "slick" % "1.0.1",
|
"com.typesafe.slick" %% "slick" % "1.0.1",
|
||||||
|
"com.novell.ldap" % "jldap" % "2009-10-07",
|
||||||
"com.h2database" % "h2" % "1.3.171",
|
"com.h2database" % "h2" % "1.3.171",
|
||||||
"ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",
|
"ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",
|
||||||
"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container",
|
"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container",
|
||||||
|
|||||||
@@ -17,12 +17,20 @@ trait SystemSettingsControllerBase extends ControllerBase with FlashMapSupport {
|
|||||||
"gravatar" -> trim(label("Gravatar", boolean())),
|
"gravatar" -> trim(label("Gravatar", boolean())),
|
||||||
"notification" -> trim(label("Notification", boolean())),
|
"notification" -> trim(label("Notification", boolean())),
|
||||||
"smtp" -> optionalIfNotChecked("notification", mapping(
|
"smtp" -> optionalIfNotChecked("notification", mapping(
|
||||||
"host" -> trim(label("SMTP Host", text(required))),
|
"host" -> trim(label("SMTP Host", text(required))),
|
||||||
"port" -> trim(label("SMTP Port", optional(number()))),
|
"port" -> trim(label("SMTP Port", optional(number()))),
|
||||||
"user" -> trim(label("SMTP User", optional(text()))),
|
"user" -> trim(label("SMTP User", optional(text()))),
|
||||||
"password" -> trim(label("SMTP Password", optional(text()))),
|
"password" -> trim(label("SMTP Password", optional(text()))),
|
||||||
"ssl" -> trim(label("Enable SSL", optional(boolean())))
|
"ssl" -> trim(label("Enable SSL", optional(boolean())))
|
||||||
)(Smtp.apply))
|
)(Smtp.apply)),
|
||||||
|
"authType" -> trim(label("Auth Type", text(required))),
|
||||||
|
"ldap" -> optional(_.get("authType") == Some("LDAP"), mapping(
|
||||||
|
"host" -> trim(label("LDAP host", text(required))),
|
||||||
|
"port" -> trim(label("LDAP port", number(required))),
|
||||||
|
"baseDN" -> trim(label("BaseDN", text(required))),
|
||||||
|
"userNameAttribute" -> trim(label("User name attribute", text(required))),
|
||||||
|
"mailAttribute" -> trim(label("Mail address attribute", text(required)))
|
||||||
|
)(Ldap.apply))
|
||||||
)(SystemSettings.apply)
|
)(SystemSettings.apply)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,15 @@ trait SystemSettingsService {
|
|||||||
smtp.ssl.foreach(x => props.setProperty(SmtpSsl, x.toString))
|
smtp.ssl.foreach(x => props.setProperty(SmtpSsl, x.toString))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(settings.authType == "LDAP"){
|
||||||
|
settings.ldap.map { ldap =>
|
||||||
|
props.setProperty(LdapHost, ldap.host)
|
||||||
|
props.setProperty(LdapPort, ldap.port.toString)
|
||||||
|
props.setProperty(LdapBaseDN, ldap.baseDN)
|
||||||
|
props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute)
|
||||||
|
props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute)
|
||||||
|
}
|
||||||
|
}
|
||||||
props.store(new java.io.FileOutputStream(GitBucketConf), null)
|
props.store(new java.io.FileOutputStream(GitBucketConf), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +50,17 @@ trait SystemSettingsService {
|
|||||||
getOptionValue[Boolean](props, SmtpSsl, None)))
|
getOptionValue[Boolean](props, SmtpSsl, None)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
},
|
||||||
|
getValue(props, AuthType, ""),
|
||||||
|
if(getValue(props, AuthType, "") == "LDAP"){
|
||||||
|
Some(Ldap(
|
||||||
|
getValue(props, LdapHost, ""),
|
||||||
|
getValue(props, LdapPort, 389),
|
||||||
|
getValue(props, LdapBaseDN, ""),
|
||||||
|
getValue(props, LdapUserNameAttribute, "uid"),
|
||||||
|
getValue(props, LdapUserNameAttribute, "mail")))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -54,8 +74,17 @@ object SystemSettingsService {
|
|||||||
allowAccountRegistration: Boolean,
|
allowAccountRegistration: Boolean,
|
||||||
gravatar: Boolean,
|
gravatar: Boolean,
|
||||||
notification: Boolean,
|
notification: Boolean,
|
||||||
smtp: Option[Smtp]
|
smtp: Option[Smtp],
|
||||||
)
|
authType: String,
|
||||||
|
ldap: Option[Ldap])
|
||||||
|
|
||||||
|
case class Ldap(
|
||||||
|
host: String,
|
||||||
|
port: Int,
|
||||||
|
baseDN: String,
|
||||||
|
userNameAttribute: String,
|
||||||
|
mailAttribute: String)
|
||||||
|
|
||||||
case class Smtp(
|
case class Smtp(
|
||||||
host: String,
|
host: String,
|
||||||
port: Option[Int],
|
port: Option[Int],
|
||||||
@@ -65,12 +94,18 @@ object SystemSettingsService {
|
|||||||
|
|
||||||
private val AllowAccountRegistration = "allow_account_registration"
|
private val AllowAccountRegistration = "allow_account_registration"
|
||||||
private val Gravatar = "gravatar"
|
private val Gravatar = "gravatar"
|
||||||
|
private val AuthType = "auth_type"
|
||||||
private val Notification = "notification"
|
private val Notification = "notification"
|
||||||
private val SmtpHost = "smtp.host"
|
private val SmtpHost = "smtp.host"
|
||||||
private val SmtpPort = "smtp.port"
|
private val SmtpPort = "smtp.port"
|
||||||
private val SmtpUser = "smtp.user"
|
private val SmtpUser = "smtp.user"
|
||||||
private val SmtpPassword = "smtp.password"
|
private val SmtpPassword = "smtp.password"
|
||||||
private val SmtpSsl = "smtp.ssl"
|
private val SmtpSsl = "smtp.ssl"
|
||||||
|
private val LdapHost = "ldap.host"
|
||||||
|
private val LdapPort = "ldap.port"
|
||||||
|
private val LdapBaseDN = "ldap.baseDN"
|
||||||
|
private val LdapUserNameAttribute = "ldap.username_attribute"
|
||||||
|
private val LdapMailAddressAttribute = "ldap.mail_attribute"
|
||||||
|
|
||||||
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
|
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
|
||||||
val value = props.getProperty(key)
|
val value = props.getProperty(key)
|
||||||
|
|||||||
49
src/main/scala/util/LDAPUtil.scala
Normal file
49
src/main/scala/util/LDAPUtil.scala
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import service.SystemSettingsService.Ldap
|
||||||
|
import com.novell.ldap.LDAPConnection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for LDAP authentication.
|
||||||
|
*/
|
||||||
|
object LDAPUtil extends App {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try authentication by LDAP using given configuration.
|
||||||
|
* Returns Right(mailAddress) if authentication is successful, otherwise Left(errorMessage).
|
||||||
|
*/
|
||||||
|
def authenticate(ldapSettings: Ldap, userName: String, password: String): Either[String, String] = {
|
||||||
|
var conn: LDAPConnection = null
|
||||||
|
try {
|
||||||
|
conn = new LDAPConnection()
|
||||||
|
conn.connect(ldapSettings.host, ldapSettings.port)
|
||||||
|
val userDN = ldapSettings.userNameAttribute + "=" + userName + ",ou=Users," + ldapSettings.baseDN
|
||||||
|
conn.bind(3, userDN, password.getBytes)
|
||||||
|
if(conn.isBound){
|
||||||
|
val results = conn.search(userDN, LDAPConnection.SCOPE_BASE, "", Array[String](ldapSettings.mailAttribute), false)
|
||||||
|
var mailAddress: String = null
|
||||||
|
while(results.hasMore){
|
||||||
|
mailAddress = results.next.getAttribute(ldapSettings.mailAttribute).getStringValue
|
||||||
|
}
|
||||||
|
if(mailAddress != null){
|
||||||
|
Right(mailAddress)
|
||||||
|
} else {
|
||||||
|
Left("Can't find mail address.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Left("Authentication failed.")
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case ex: Exception => Left(ex.getMessage)
|
||||||
|
} finally {
|
||||||
|
if(conn != null){
|
||||||
|
conn.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// val ldapSettings = Ldap("192.168.159.128", 389, "dc=unix-power,dc=net", "uid", "mail")
|
||||||
|
//
|
||||||
|
// println(authenticate(ldapSettings, "tanaka", "password"))
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header">System Settings</div>
|
<div class="box-header">System Settings</div>
|
||||||
<div class="box-content">
|
<div class="box-content">
|
||||||
|
<!--====================================================================-->
|
||||||
|
<!-- Account registration -->
|
||||||
|
<!--====================================================================-->
|
||||||
<label><strong>Account registration</strong></label>
|
<label><strong>Account registration</strong></label>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>
|
<label>
|
||||||
@@ -19,6 +22,9 @@
|
|||||||
<strong>Deny</strong> - Only administrators can create account.
|
<strong>Deny</strong> - Only administrators can create account.
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<!--====================================================================-->
|
||||||
|
<!-- Services -->
|
||||||
|
<!--====================================================================-->
|
||||||
<hr>
|
<hr>
|
||||||
<label><strong>Services</strong></label>
|
<label><strong>Services</strong></label>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@@ -27,6 +33,63 @@
|
|||||||
Gravatar
|
Gravatar
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<!--====================================================================-->
|
||||||
|
<!-- Authentication -->
|
||||||
|
<!--====================================================================-->
|
||||||
|
<hr>
|
||||||
|
<label><strong>Authentication</strong></label>
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
<input type="radio" id="authTypeDefault" name="authType" value="Default"@if(settings.authType != "LDAP"){ checked}/>
|
||||||
|
Default
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
<input type="radio" id="authTypeLDAP" name="authType" value="LDAP"@if(settings.authType == "LDAP"){ checked}/>
|
||||||
|
LDAP
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-horizontal ldap">
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="ldapHost">LDAP Host</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="ldapHost" name="ldap.host" value="@settings.ldap.map(_.host)"/>
|
||||||
|
<span id="error-ldap_host" class="error"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="ldapPort">LDAP Port</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="ldapPort" name="ldap.port" class="input-mini" value="@settings.ldap.map(_.port)"/>
|
||||||
|
<span id="error-ldap_port" class="error"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="ldapBaseDN">BaseDN</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="ldapBaseDN" name="ldap.baseDN" value="@settings.ldap.map(_.baseDN)"/>
|
||||||
|
<span id="error-ldap_baseDN" class="error"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="ldapUserNameAttribute">User name attribute</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="ldapUserNameAttribute" name="ldap.userNameAttribute" value="@settings.ldap.map(_.userNameAttribute)"/>
|
||||||
|
<span id="error-ldap_userNameAttribute" class="error"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="ldapMailAttribute">Mail address attribute</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="ldapMailAttribute" name="ldap.mailAttribute" value="@settings.ldap.map(_.mailAttribute)"/>
|
||||||
|
<span id="error-ldap_mailAttribute" class="error"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--====================================================================-->
|
||||||
|
<!-- Notification email -->
|
||||||
|
<!--====================================================================-->
|
||||||
<hr>
|
<hr>
|
||||||
<label><strong>Notification email</strong></label>
|
<label><strong>Notification email</strong></label>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@@ -35,7 +98,7 @@
|
|||||||
Send notifications
|
Send notifications
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div class="form-horizontal">
|
<div class="form-horizontal notification">
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="smtpHost">SMTP Host</label>
|
<label class="control-label" for="smtpHost">SMTP Host</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
@@ -81,7 +144,12 @@
|
|||||||
<script>
|
<script>
|
||||||
$(function(){
|
$(function(){
|
||||||
$('#notification').change(function(){
|
$('#notification').change(function(){
|
||||||
$('.form-horizontal input').prop('disabled', !$(this).prop('checked'));
|
$('.notification input').prop('disabled', !$(this).prop('checked'));
|
||||||
}).change();
|
}).change();
|
||||||
|
|
||||||
|
$('input[name=authType]').click(function(){
|
||||||
|
$('.ldap input').prop('disabled', $('input[name=authType]:checked').val() != "LDAP");
|
||||||
|
});
|
||||||
|
$('input[name=authType]:checked').click();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user