ldap登录时支持邮箱作为账户

pull/822/head
gsw945 2022-09-02 10:41:35 +08:00
parent 25f9d34edb
commit 221b9deaaa
5 changed files with 77 additions and 21 deletions

View File

@ -125,7 +125,9 @@ ldap_host=ad.example.com
#ldap端口
ldap_port=3268
#ldap内哪个属性作为用户名
ldap_attribute=sAMAccountName
ldap_account=sAMAccountName
#ldap内哪个属性作为邮箱
ldap_mail=mail
#搜索范围
ldap_base=DC=example,DC=com
#第一次绑定ldap用户dn

View File

@ -0,0 +1 @@
go build -v -ldflags "-linkmode external -extldflags '-static' -w" -o mindoc_windows_amd64.exe main.go

5
go.mod
View File

@ -7,6 +7,7 @@ require (
github.com/beego/beego/v2 v2.0.5
github.com/beego/i18n v0.0.0-20161101132742-e9308947f407
github.com/boombuler/barcode v1.0.1
github.com/go-ldap/ldap/v3 v3.4.4
github.com/howeyc/fsnotify v0.9.0
github.com/kardianos/service v1.2.1
github.com/lifei6671/gocaptcha v0.2.0
@ -18,11 +19,13 @@ require (
)
require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/Unknwon/goconfig v1.0.0 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-redis/redis/v7 v7.4.1 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
@ -38,7 +41,7 @@ require (
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rivo/uniseg v0.3.4 // indirect
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d // indirect
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect

17
go.sum
View File

@ -31,6 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft7pkxDf6WoUvEZJ/uOKsvtpjLnn8MU=
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
@ -76,6 +78,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-asn1-ber/asn1-ber v1.5.0 h1:/S4hO/AO6tLMlPX0oftGSOcdGJJN/MuYzfgWRMn199E=
github.com/go-asn1-ber/asn1-ber v1.5.0/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -83,6 +87,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@ -250,15 +256,16 @@ github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -274,6 +281,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -340,6 +348,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=

View File

@ -15,7 +15,7 @@ import (
"strings"
"time"
"gopkg.in/ldap.v2"
"github.com/go-ldap/ldap/v3"
"math"
@ -119,14 +119,14 @@ func (m *Member) TmpLogin(account string) (*Member, error) {
return member, nil
}
//ldapLogin 通过LDAP登陆
// ldapLogin 通过LDAP登陆
func (m *Member) ldapLogin(account string, password string) (*Member, error) {
if !web.AppConfig.DefaultBool("ldap_enable", false) {
return m, ErrMemberAuthMethodInvalid
}
var err error
ldaphost, _ := web.AppConfig.String("ldap_host")
lc, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldaphost, web.AppConfig.DefaultInt("ldap_port", 3268)))
lc, err := ldap.DialURL(fmt.Sprintf("ldap://%s:%d", ldaphost, web.AppConfig.DefaultInt("ldap_port", 3268)))
if err != nil {
logs.Error("绑定 LDAP 用户失败 ->", err)
return m, ErrLDAPConnect
@ -141,13 +141,23 @@ func (m *Member) ldapLogin(account string, password string) (*Member, error) {
}
ldapbase, _ := web.AppConfig.String("ldap_base")
ldapfilter, _ := web.AppConfig.String("ldap_filter")
ldapattr, _ := web.AppConfig.String("ldap_attribute")
ldapaccount, _ := web.AppConfig.String("ldap_account")
ldapmail, _ := web.AppConfig.String("ldap_mail")
// 判断account是否是email
isEmail := false
var email string
ldapattr := ldapaccount
if ok, err := regexp.MatchString(conf.RegexpEmail, account); ok && err == nil {
isEmail = true
email = account
ldapattr = ldapmail
}
searchRequest := ldap.NewSearchRequest(
ldapbase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
//修改objectClass通过配置文件获取值
// 修改objectClass通过配置文件获取值
fmt.Sprintf("(&(%s)(%s=%s))", ldapfilter, ldapattr, account),
[]string{"dn", "mail"},
[]string{"dn", "mail", "cn", "ou", "sAMAccountName"},
nil,
)
searchResult, err := lc.Search(searchRequest)
@ -164,10 +174,33 @@ func (m *Member) ldapLogin(account string, password string) (*Member, error) {
logs.Error("绑定 LDAP 用户失败 ->", err)
return m, ErrorMemberPasswordError
}
ldap_cn := searchResult.Entries[0].GetAttributeValue("cn")
ldap_mail := searchResult.Entries[0].GetAttributeValue(ldapmail) // "mail"
ldap_account := searchResult.Entries[0].GetAttributeValue(ldapaccount) // "sAMAccountName"
m.RealName = ldap_cn
m.Account = ldap_account
m.AuthMethod = "ldap"
// 如果ldap配置了email
if len(ldap_mail) > 0 && strings.Contains(ldap_mail, "@") {
// 如果member已配置email
if len(m.Email) > 0 {
// 如果member配置的email和ldap配置的email不同
if m.Email != ldap_mail {
return m, errors.New(fmt.Sprintf("ldap配置的email(%s)与数据库中已有email({%s})不同, 请联系管理员修改", ldap_mail, m.Email))
}
} else {
// 如果member未配置email则用ldap的email配置
m.Email = ldap_mail
}
} else {
// 如果ldap未配置email则直接绑定到member
if isEmail {
m.Email = email
}
}
if m.MemberId <= 0 {
m.Account = account
m.Email = searchResult.Entries[0].GetAttributeValue("mail")
m.AuthMethod = "ldap"
m.Avatar = "/static/images/headimgurl.jpg"
m.Role = conf.SystemRole(web.AppConfig.DefaultInt("ldap_user_role", 2))
m.CreateTime = time.Now()
@ -178,6 +211,14 @@ func (m *Member) ldapLogin(account string, password string) (*Member, error) {
return m, ErrorMemberPasswordError
}
m.ResolveRoleName()
} else {
// 更新ldap信息
err = m.Update("account", "real_name", "email", "auth_method")
if err != nil {
logs.Error("LDAP更新用户信息失败", err)
return m, errors.New("LDAP更新用户信息失败")
}
m.ResolveRoleName()
}
return m, nil
}
@ -338,7 +379,7 @@ func (m *Member) ResolveRoleName() {
}
}
//根据账号查找用户.
// 根据账号查找用户.
func (m *Member) FindByAccount(account string) (*Member, error) {
o := orm.NewOrm()
@ -350,7 +391,7 @@ func (m *Member) FindByAccount(account string) (*Member, error) {
return m, err
}
//批量查询用户
// 批量查询用户
func (m *Member) FindByAccountList(accounts ...string) ([]*Member, error) {
o := orm.NewOrm()
@ -365,7 +406,7 @@ func (m *Member) FindByAccountList(accounts ...string) ([]*Member, error) {
return members, err
}
//分页查找用户.
// 分页查找用户.
func (m *Member) FindToPager(pageIndex, pageSize int) ([]*Member, int, error) {
o := orm.NewOrm()
@ -399,7 +440,7 @@ func (m *Member) IsAdministrator() bool {
return m.Role == 0 || m.Role == 1
}
//根据指定字段查找用户.
// 根据指定字段查找用户.
func (m *Member) FindByFieldFirst(field string, value interface{}) (*Member, error) {
o := orm.NewOrm()
@ -408,7 +449,7 @@ func (m *Member) FindByFieldFirst(field string, value interface{}) (*Member, err
return m, err
}
//校验用户.
// 校验用户.
func (m *Member) Valid(is_hash_password bool) error {
//邮箱不能为空
@ -464,7 +505,7 @@ func (m *Member) Valid(is_hash_password bool) error {
return nil
}
//删除一个用户.
// 删除一个用户.
func (m *Member) Delete(oldId int, newId int) error {
ormer := orm.NewOrm()