Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:增加设置新密码时强度校验功能 #224

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions logic/user_logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ func (l UserLogic) ChangePwd(c *gin.Context, req interface{}) (data interface{},
if tools.NewParPasswd(user.Password) != r.OldPassword {
return nil, tools.NewValidatorError(fmt.Errorf("原密码错误"))
}

err = tools.CheckPasswdStrength(r.NewPassword)
if err != nil {
return nil, tools.NewValidatorError(err)
}

// ldap更新密码时可以直接指定用户DN和新密码即可更改成功
err = ildap.User.ChangePwd(user.UserDN, "", r.NewPassword)
if err != nil {
Expand Down
84 changes: 84 additions & 0 deletions public/tools/check_passwd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package tools

import (
"fmt"
"strings"
"unicode"
)

/*
新密码规则:
1. 8位(包含)-16位(包含)
2. 包含至少一个拉丁大写字母
3. 包含至少一个拉丁小写字母
4. 包含至少一个数字
5.包含至少一个特殊字符 !@#%^&*()-_+={}][|;:<>,.?
6. 密码不能包含空格,特殊unicode字符
*/

// 校验新密码强度是否符合规则
func CheckPasswdStrength(newPasswd string) (err error) {
// 校验密码长度
if len(newPasswd) < 8 || len(newPasswd) > 16 {
return fmt.Errorf("密码长度不符合规则")
}

// flags[0] hasUpper
// flags[1] hasLower
// flags[2] hasNumber
// flags[3] hasSpecial
var flags = make([]bool, 4)

// 以unicode字符形式遍历
for _, u := range newPasswd {
// 密码不能包含空格
if unicode.IsSpace(u) {
return fmt.Errorf("密码不能包含空格")
}

// 如果既不是大小写字母,也不是数字,也不是标点符号
// 为什么不用unicode.IsLetter()是为了排除如'æ'拉丁字母的干扰
if !isLetter(u) && !unicode.IsNumber(u) && !isSpecial(u) {
return fmt.Errorf("密码不能包含Unicode特殊字符")
}

// 判断是否为大写字母
if unicode.IsUpper(u) {
flags[0] = true
}

// 判断是否为小写字母
if unicode.IsLower(u) {
flags[1] = true
}

// 判断是否为数字
if unicode.IsNumber(u) {
flags[2] = true
}

// 判断特殊字符
if isSpecial(u) {
flags[3] = true
}
}

// 判断四个条件是否满足
for _, flag := range flags {
if !flag {
return fmt.Errorf("密码不符合规则")
}
}

return nil
}

// 判断特殊字符
func isSpecial(u rune) bool {
return strings.Contains("!@#%^&*()-_+={}][|;:<>,.?", string(u))
}

// 判断是否为拉丁字母
func isLetter(u rune) bool {
return (u >= 'a' && u <= 'z') || (u >= 'A' && u <= 'Z')
}
50 changes: 50 additions & 0 deletions public/tools/util_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tools

import (
"errors"
"fmt"
"testing"
)
Expand Down Expand Up @@ -37,3 +38,52 @@ func TestEncodePass(t *testing.T) {
fmt.Println("its not match")
}
}

// 测试密码强度是否符合规则
func TestNewPasswdStrength(t *testing.T) {
tests := []struct {
name string
pwd string
err error
}{
// TODO: Add test cases.
{name: "[False]长度不足8", pwd: "abc@!Q", err: errors.New("pasword invalid")},
{name: "[False]长度大于16", pwd: "abc@!Qaaassss3729128aaaaaaaaa", err: errors.New("pasword invalid")},
{name: "[False]包含空格", pwd: "abAa a32!aCa", err: errors.New("pasword invalid")},
{name: "[False]全大写", pwd: "AAGGGAAGAAAAAA", err: errors.New("pasword invalid")},
{name: "[False]全小写", pwd: "abcabcabc", err: errors.New("pasword invalid")},
{name: "[False]全数字", pwd: "111111111", err: errors.New("pasword invalid")},
{name: "[False]全特殊字符", pwd: "!@#$%^&*(()_+", err: errors.New("pasword invalid")},

{name: "[False]大写+小写", pwd: "abcabcQQQQ", err: errors.New("pasword invalid")},
{name: "[False]大写+数字", pwd: "1111QQQQ", err: errors.New("pasword invalid")},
{name: "[False]大写+特殊字符", pwd: "QQQQA(())", err: errors.New("pasword invalid")},
{name: "[False]小写+数字", pwd: "abcabc7890", err: errors.New("pasword invalid")},
{name: "[False]小写+特殊字符", pwd: "abcabc.(())", err: errors.New("pasword invalid")},
{name: "[False]数字+特殊字符", pwd: "12345678&()", err: errors.New("pasword invalid")},
{name: "[False]大写+小写+数字", pwd: "AAcabc7890", err: errors.New("pasword invalid")},
{name: "[False]大写+小写+特殊字符", pwd: "aBcabcQ(A)Q", err: errors.New("pasword invalid")},
{name: "[False]小写+数字+特殊字符", pwd: "abc1239)))", err: errors.New("pasword invalid")},

{name: "[False]unicode特殊字符#00", pwd: "æææææAb#c1", err: errors.New("pasword invalid")},
{name: "[False]unicode特殊字符#01", pwd: "\b5Ὂg̀9! ℃ᾭG", err: errors.New("pasword invalid")},
{name: "[False]unicode特殊字符#02", pwd: "中文是密码Ý", err: errors.New("pasword invalid")},
{name: "[False]unicode特殊字符#03", pwd: "notEng3.14Ý", err: errors.New("pasword invalid")},
{name: "[False]unicode特殊字符#04", pwd: "ĒNĜĹis Ĥ", err: errors.New("pasword invalid")},
{name: "[False]unicode特殊字符#05", pwd: "😂😂😂😂😂", err: errors.New("pasword invalid")},

{name: "[True]大写-小写-数字-特殊字符", pwd: "AbcFAc.163606", err: nil},
{name: "[True]大写-小写-数字-特殊字符", pwd: "AbcP1bc!!#.#", err: nil},
{name: "[True]大写-小写数字-特殊字符", pwd: "AUbEXZ#14159", err: nil},
{name: "[True]大写-小写-数字-特殊字符", pwd: "iyTmqp@14159", err: nil},
{name: "[True]大写-小写-数字-特殊字符", pwd: "G1thub:liuup", err: nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := CheckPasswdStrength(tt.pwd)
if (err != nil && tt.err == nil) || (err == nil && tt.err != nil) {
t.Errorf("CheckPasswdStrength() error = %v", err)
}
})
}
}
Loading