소스 검색

ldap integration

AY's Macbook Pro 3 년 전
부모
커밋
065a13ac19
7개의 변경된 파일114개의 추가작업 그리고 51개의 파일을 삭제
  1. 4 1
      ldap.go
  2. 2 1
      main.router.go
  3. 45 2
      mod/auth/ldap/ldap.go
  4. 17 4
      mod/auth/ldap/ldapreader/reader.go
  5. 7 6
      mod/common/template.go
  6. 37 36
      system.resetpw.go
  7. 2 1
      web/login.system

+ 4 - 1
ldap.go

@@ -9,7 +9,7 @@ import (
 
 func ldapInit() {
 	//ldap
-	ldapHandler := ldap.NewLdapHandler(authAgent, registerHandler, sysdb, permissionHandler, userHandler)
+	ldapHandler := ldap.NewLdapHandler(authAgent, registerHandler, sysdb, permissionHandler, userHandler, iconSystem)
 
 	//add a entry to the system settings
 	adminRouter := prout.NewModuleRouter(prout.RouterOption{
@@ -34,4 +34,7 @@ func ldapInit() {
 	adminRouter.HandleFunc("/system/auth/ldap/config/testConnection", ldapHandler.TestConnection)
 	adminRouter.HandleFunc("/system/auth/ldap/config/syncorizeUser", ldapHandler.SynchronizeUser)
 
+	//login interface and login handler
+	http.HandleFunc("/system/auth/ldap/login", ldapHandler.HandleLogin)
+	http.HandleFunc("/ldapLogin.system", ldapHandler.HandleLoginPage)
 }

+ 2 - 1
main.router.go

@@ -37,10 +37,11 @@ func mrouter(h http.Handler) http.Handler {
 				imgsrc = "./web/img/public/auth_icon.png"
 			}
 			imageBase64, _ := LoadImageAsBase64(imgsrc)
-			parsedPage, err := template_load("web/login.system", map[string]interface{}{
+			parsedPage, err := common.Templateload("web/login.system", map[string]interface{}{
 				"redirection_addr": red,
 				"usercount":        strconv.Itoa(authAgent.GetUserCounts()),
 				"service_logo":     imageBase64,
+				"login_addr":       "system/auth/login",
 			})
 			if err != nil {
 				panic("Error. Unable to parse login page. Is web directory data exists?")

+ 45 - 2
mod/auth/ldap/ldap.go

@@ -23,6 +23,7 @@ type ldapHandler struct {
 	coredb            *db.Database
 	permissionHandler *permission.PermissionHandler
 	userHandler       *user.UserHandler
+	iconSystem        string
 }
 
 type Config struct {
@@ -46,7 +47,7 @@ TODO: stop user to syncorize if the current user will lost admin access
 */
 
 //NewLdapHandler xxx
-func NewLdapHandler(authAgent *auth.AuthAgent, register *reg.RegisterHandler, coreDb *db.Database, permissionHandler *permission.PermissionHandler, userHandler *user.UserHandler) *ldapHandler {
+func NewLdapHandler(authAgent *auth.AuthAgent, register *reg.RegisterHandler, coreDb *db.Database, permissionHandler *permission.PermissionHandler, userHandler *user.UserHandler, iconSystem string) *ldapHandler {
 	//ldap handler init
 	log.Println("Starting LDAP client...")
 	err := coreDb.NewTable("ldap")
@@ -68,6 +69,7 @@ func NewLdapHandler(authAgent *auth.AuthAgent, register *reg.RegisterHandler, co
 		coredb:            coreDb,
 		permissionHandler: permissionHandler,
 		userHandler:       userHandler,
+		iconSystem:        iconSystem,
 	}
 
 	return &LDAPHandler
@@ -196,7 +198,7 @@ func (ldap *ldapHandler) getAllUser(limit int) []UserAccount {
 			EquivGroup = append(EquivGroup, ldap.reg.DefaultUserGroup)
 		}
 		account := UserAccount{
-			Username:   v.GetAttributeValue("uid"),
+			Username:   v.GetAttributeValue("cn"),
 			Group:      Group,
 			EquivGroup: EquivGroup,
 		}
@@ -281,3 +283,44 @@ func (ldap *ldapHandler) SynchronizeUser(w http.ResponseWriter, r *http.Request)
 	}
 	common.SendOK(w)
 }
+
+//LOGIN related command
+
+func (ldap *ldapHandler) HandleLoginPage(w http.ResponseWriter, r *http.Request) {
+	red, _ := common.Mv(r, "redirect", false)
+
+	//Append the redirection addr into the template
+	imgsrc := "./web/" + ldap.iconSystem
+	if !common.FileExists(imgsrc) {
+		imgsrc = "./web/img/public/auth_icon.png"
+	}
+	imageBase64, _ := common.LoadImageAsBase64(imgsrc)
+	parsedPage, err := common.Templateload("web/login.system", map[string]interface{}{
+		"redirection_addr": red,
+		"usercount":        strconv.Itoa(ldap.ag.GetUserCounts()),
+		"service_logo":     imageBase64,
+		"login_addr":       "system/ldap/auth/login",
+	})
+	if err != nil {
+		panic("Error. Unable to parse login page. Is web directory data exists?")
+	}
+	w.Header().Add("Content-Type", "text/html; charset=UTF-8")
+	w.Write([]byte(parsedPage))
+}
+
+func (ldap *ldapHandler) HandleLogin(w http.ResponseWriter, r *http.Request) {
+	username, err := common.Mv(r, "username", true)
+	if err != nil {
+		common.SendErrorResponse(w, err.Error())
+		return
+	}
+	password, err := common.Mv(r, "password", true)
+	if err != nil {
+		common.SendErrorResponse(w, err.Error())
+		return
+	}
+	loginInfo, err := ldap.ldapreader.Authenticate(username, password)
+	//authencate successful
+	//common
+
+}

+ 17 - 4
mod/auth/ldap/ldapreader/reader.go

@@ -27,7 +27,7 @@ func NewLDAPReader(username string, password string, server string, basedn strin
 }
 
 func (handler *LdapReader) GetUser(username string) (*ldap.Entry, error) {
-	returnVal, err := handler.retrieveInformation("uid="+username+","+handler.basedn, "(objectClass=*)", ldap.ScopeBaseObject)
+	returnVal, err := handler.retrieveInformation("uid="+username+","+handler.basedn, "(objectClass=*)", ldap.ScopeBaseObject, handler.username, handler.password)
 	if err != nil {
 		return nil, err
 	}
@@ -38,17 +38,30 @@ func (handler *LdapReader) GetUser(username string) (*ldap.Entry, error) {
 }
 
 func (handler *LdapReader) GetAllUser() ([]*ldap.Entry, error) {
-	return handler.retrieveInformation(handler.basedn, "(objectClass=*)", ldap.ScopeWholeSubtree)
+	return handler.retrieveInformation(handler.basedn, "(objectClass=*)", ldap.ScopeWholeSubtree, handler.username, handler.password)
 }
 
-func (handler *LdapReader) retrieveInformation(dn string, filter string, typeOfSearch int) ([]*ldap.Entry, error) {
+func (handler *LdapReader) Authenticate(username string, password string) (bool, error) {
+	userInformation, err := handler.retrieveInformation("uid="+username+","+handler.basedn, "(objectClass=*)", ldap.ScopeBaseObject, handler.username, handler.password)
+	if err != nil {
+		return false, err
+	}
+	if len(userInformation) > 0 {
+		if userInformation[0].GetAttributeValue("cn") == username {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+func (handler *LdapReader) retrieveInformation(dn string, filter string, typeOfSearch int, username string, password string) ([]*ldap.Entry, error) {
 	ldapURL, err := ldap.DialURL(fmt.Sprintf("ldap://%s:389", handler.server))
 	if err != nil {
 		return nil, err
 	}
 	defer ldapURL.Close()
 
-	ldapURL.Bind(handler.username, handler.password)
+	ldapURL.Bind(username, password)
 	searchReq := ldap.NewSearchRequest(
 		dn,
 		typeOfSearch,

+ 7 - 6
template.go → mod/common/template.go

@@ -1,8 +1,9 @@
-package main
+package common
 
 import (
-	"github.com/valyala/fasttemplate"
 	"io/ioutil"
+
+	"github.com/valyala/fasttemplate"
 )
 
 /*
@@ -11,12 +12,12 @@ import (
 	This is the main system core module that perform function similar to what PHP did.
 	To replace part of the content of any file, use {{paramter}} to replace it.
 
-	
+
 */
 
-func template_load(filename string, replacement map[string]interface{}) (string, error){
+func Templateload(filename string, replacement map[string]interface{}) (string, error) {
 	content, err := ioutil.ReadFile(filename)
-	if (err != nil){
+	if err != nil {
 		return "", nil
 	}
 	t := fasttemplate.New(string(content), "{{", "}}")
@@ -24,7 +25,7 @@ func template_load(filename string, replacement map[string]interface{}) (string,
 	return string(s), nil
 }
 
-func template_apply(templateString string, replacement map[string]interface{}) string{
+func TemplateApply(templateString string, replacement map[string]interface{}) string {
 	t := fasttemplate.New(templateString, "{{", "}}")
 	s := t.ExecuteString(replacement)
 	return string(s)

+ 37 - 36
system.resetpw.go

@@ -1,11 +1,12 @@
 package main
 
 import (
-	"net/http"
-	"log"
 	"errors"
+	"log"
+	"net/http"
 
 	auth "imuslab.com/arozos/mod/auth"
+	"imuslab.com/arozos/mod/common"
 )
 
 /*
@@ -14,20 +15,20 @@ import (
 	This module exists to serve the password restart page with security check
 */
 
-func system_resetpw_init(){
-	http.HandleFunc("/system/reset/validateResetKey", system_resetpw_validateResetKeyHandler);
-	http.HandleFunc("/system/reset/confirmPasswordReset", system_resetpw_confirmReset);
+func system_resetpw_init() {
+	http.HandleFunc("/system/reset/validateResetKey", system_resetpw_validateResetKeyHandler)
+	http.HandleFunc("/system/reset/confirmPasswordReset", system_resetpw_confirmReset)
 }
 
 //Validate if the ysername and rkey is valid
-func system_resetpw_validateResetKeyHandler(w http.ResponseWriter, r *http.Request){
+func system_resetpw_validateResetKeyHandler(w http.ResponseWriter, r *http.Request) {
 	username, err := mv(r, "username", true)
-	if err != nil{
+	if err != nil {
 		sendErrorResponse(w, "Invalid username or key")
 		return
 	}
 	rkey, err := mv(r, "rkey", true)
-	if err != nil{
+	if err != nil {
 		sendErrorResponse(w, "Invalid username or key")
 		return
 	}
@@ -39,7 +40,7 @@ func system_resetpw_validateResetKeyHandler(w http.ResponseWriter, r *http.Reque
 
 	//Check if the pair is valid
 	err = system_resetpw_validateResetKey(username, rkey)
-	if err != nil{
+	if err != nil {
 		sendErrorResponse(w, err.Error())
 		return
 	}
@@ -48,68 +49,68 @@ func system_resetpw_validateResetKeyHandler(w http.ResponseWriter, r *http.Reque
 
 }
 
-func system_resetpw_confirmReset(w http.ResponseWriter, r *http.Request){
+func system_resetpw_confirmReset(w http.ResponseWriter, r *http.Request) {
 	username, _ := mv(r, "username", true)
 	rkey, _ := mv(r, "rkey", true)
 	newpw, _ := mv(r, "pw", true)
-	if (username == "" || rkey == "" || newpw == ""){
+	if username == "" || rkey == "" || newpw == "" {
 		sendErrorResponse(w, "Internal Server Error")
 		return
 	}
 
 	//Check user exists
-	if !authAgent.UserExists(username){
+	if !authAgent.UserExists(username) {
 		sendErrorResponse(w, "Username not exists")
 		return
 	}
 
 	//Validate rkey
 	err := system_resetpw_validateResetKey(username, rkey)
-	if err != nil{
+	if err != nil {
 		sendErrorResponse(w, err.Error())
 		return
 	}
 
 	//OK to procced
 	newHashedPassword := auth.Hash(newpw)
-	err = sysdb.Write("auth", "passhash/" + username, newHashedPassword)
-	if err != nil{
+	err = sysdb.Write("auth", "passhash/"+username, newHashedPassword)
+	if err != nil {
 		sendErrorResponse(w, err.Error())
 		return
 	}
 
-	sendOK(w);
+	sendOK(w)
 
 }
 
-func system_resetpw_validateResetKey(username string, key string) error{
+func system_resetpw_validateResetKey(username string, key string) error {
 	//Get current password from db
 	passwordInDB := ""
-	err := sysdb.Read("auth", "passhash/" + username, &passwordInDB)
-	if err != nil{
+	err := sysdb.Read("auth", "passhash/"+username, &passwordInDB)
+	if err != nil {
 		return err
 	}
 
 	//Get hashed user key
 	hashedKey := auth.Hash(key)
-	if (passwordInDB != hashedKey){
+	if passwordInDB != hashedKey {
 		return errors.New("Invalid Password Reset Key")
 	}
 
 	return nil
 }
 
-func system_resetpw_handlePasswordReset(w http.ResponseWriter, r *http.Request){
+func system_resetpw_handlePasswordReset(w http.ResponseWriter, r *http.Request) {
 	//Check if the user click on this link with reset password key string. If not, ask the user to input one
 	acc, err := mv(r, "acc", false)
 	if err != nil || acc == "" {
-		system_resetpw_serveIdEnterInterface(w,r);
+		system_resetpw_serveIdEnterInterface(w, r)
 		return
 	}
 
 	resetkey, err := mv(r, "rkey", false)
 	if err != nil || resetkey == "" {
-		system_resetpw_serveIdEnterInterface(w,r);
+		system_resetpw_serveIdEnterInterface(w, r)
 		return
 	}
 
@@ -122,28 +123,28 @@ func system_resetpw_handlePasswordReset(w http.ResponseWriter, r *http.Request){
 
 	//OK. Create the New Password Entering UI
 	imageBase64, _ := LoadImageAsBase64("./web/" + iconVendor)
-	template, err := template_load("system/reset/resetPasswordTemplate.html",map[string]interface{}{
+	template, err := common.Templateload("system/reset/resetPasswordTemplate.html", map[string]interface{}{
 		"vendor_logo": imageBase64,
-		"host_name": *host_name,
-		"username": acc,
-		"rkey": resetkey,
-	});
-	if err != nil{
-		log.Fatal(err);
+		"host_name":   *host_name,
+		"username":    acc,
+		"rkey":        resetkey,
+	})
+	if err != nil {
+		log.Fatal(err)
 	}
 	w.Header().Set("Content-Type", "text/html; charset=UTF-8")
 	w.Write([]byte(template))
 }
 
-func system_resetpw_serveIdEnterInterface(w http.ResponseWriter, r *http.Request){
+func system_resetpw_serveIdEnterInterface(w http.ResponseWriter, r *http.Request) {
 	//Reset Key or Username not found, Serve entering interface
 	imageBase64, _ := LoadImageAsBase64("./web/" + iconVendor)
-	template, err := template_load("system/reset/resetCodeTemplate.html",map[string]interface{}{
+	template, err := common.Templateload("system/reset/resetCodeTemplate.html", map[string]interface{}{
 		"vendor_logo": imageBase64,
-		"host_name": *host_name,
-	});
-	if err != nil{
-		log.Fatal(err);
+		"host_name":   *host_name,
+	})
+	if err != nil {
+		log.Fatal(err)
 	}
 	w.Header().Set("Content-Type", "text/html; charset=UTF-8")
 	w.Write([]byte(template))

+ 2 - 1
web/login.system

@@ -135,6 +135,7 @@
         
     <script>
         var redirectionAddress = "{{redirection_addr}}";
+        var loginAddress = "{{login_addr}}";
         var systemUserCount = "{{usercount}}" - 0; //Magic way to convert string to int :)
         var autoRedirectTimer;
         var isMobile = false; //initiate as false
@@ -254,7 +255,7 @@
             var magic = $("#magic").val();
             var rmbme = document.getElementById("rmbme").checked;
             $("input").addClass('disabled');
-            $.post("system/auth/login", {"username": username, "password": magic, "rmbme": rmbme}).done(function(data){
+            $.post(loginAddress, {"username": username, "password": magic, "rmbme": rmbme}).done(function(data){
                 if (data.error !== undefined){
                     //Something went wrong during the login
                     $("#errmsg").text(data.error);