mirror of
				https://github.com/gitbucket/gitbucket.git
				synced 2025-10-30 18:15:59 +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", | ||||||
|   | |||||||
| @@ -22,7 +22,15 @@ trait SystemSettingsControllerBase extends ControllerBase with FlashMapSupport { | |||||||
|         "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