为了账号安全,请及时绑定邮箱和手机立即绑定

如何以编程方式在 macOS 上验证用户和密码?

如何以编程方式在 macOS 上验证用户和密码?

Go
哆啦的时光机 2022-05-10 16:01:34
我有一个应用程序询问用户的用户名和密码。目前,对于 Unix 系统(大多数),我从中读取密码哈希,/etc/shadow但对于 macOS 来说更麻烦(他们使用自己的标准),所以我想知道是否有一种简单的方法来验证用户名和密码。我正在考虑login以一种奇怪的方式使用该程序,但这不是最好的解决方案。我正在使用 golang,但 C 或 C++ 中的解决方案也会很有用。编辑@TheNextman 的答案正是我所要求的,但与其他人交谈时,他们建议我使用 PAM,因为它适用于多个操作系统。我花了一些精力来理解它,因为我正在寻找一个简单的 API 来验证用户和密码,verify(username string, password string) -> boolean但我知道 PAM 更通用,因此更复杂。但这是我最终使用的代码,它是在 GO 中使用 C 绑定制作的。package Authenticationimport "C"import (    "encoding/json"    "fmt"    "github.com/vvanpo/golang-pam")func ValidateUser(username, password string) (bool, error) {    // TODO correct handle of errors    UserPssword := userPassword{        Username : username,        Password : password,    }    b, _ := json.Marshal(UserPssword)    conn := myConHand{        username:C.CString(string(b)),    }    tx, _ := pam.Start("sshd", username, conn)    r := tx.Authenticate(0)    if r == pam.SUCCESS{        return true, nil    } else {        return false, nil    }}type userPassword struct {    Username string    Password string}type myConHand struct {    username *C.char}//C.GoStringfunc (m myConHand) RespondPAM(msg_style int, msg string) (string, bool) {    str := C.GoString(m.username)    var UserPssword userPassword    _ = json.Unmarshal([]byte(str), &UserPssword)    switch msg_style {    case pam.PROMPT_ECHO_OFF:        fmt.Println("Password!!")        return UserPssword.Password, true    case pam.PROMPT_ECHO_ON:        fmt.Println("Username!!")        return UserPssword.Username, true    case pam.ERROR_MSG:        fmt.Println(msg)        return "", true    case pam.TEXT_INFO:        fmt.Println(msg)        return "", true    default:        return "", true    }}它有一些问题,例如我正在使用该/etc/pam.d/sshd服务,因为我知道我将使用的计算机具有相同的服务,但我不知道哪个操作系统具有/etc/pam.d/sshd,另一种选择是创建我自己的服务但是我必须为我发现的每一个不同的标准创建一个 3 Linux PAM、openPAM (macos) 和 Solaris PAM。但总的来说,我认为这是一个强大的解决方案,因为我正在重用现有的身份验证机制。
查看完整描述

1 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

C 或 C++ 中的解决方案也会很有用


这是使用CoreServices的 C 语言示例。为简洁起见,省略了错误和结果检查:


void on_logon(const char* username, const char* password) {

    CSIdentityQueryRef query;

    CFArrayRef idArray = NULL;

    CSIdentityRef result;

    CFStringRef cfUsername = NULL;

    CFStringRef cfPassword = NULL;


    cfUsername = CFStringCreateWithCString(NULL, username, kCFStringEncodingUTF8);

    query = CSIdentityQueryCreateForName(kCFAllocatorDefault, cfUsername, kCSIdentityQueryStringEquals, kCSIdentityClassUser,    CSGetDefaultIdentityAuthority());


    CSIdentityQueryExecute(query, kCSIdentityQueryGenerateUpdateEvents, NULL);


    idArray = CSIdentityQueryCopyResults(query);


    if (CFArrayGetCount(idArray) != 1)

    {

        // Username didn't match...

    }


    result = (CSIdentityRef) CFArrayGetValueAtIndex(idArray, 0);


    cfPassword = CFStringCreateWithCString(NULL, password, kCFStringEncodingUTF8);


    if (CSIdentityAuthenticateUsingPassword(result, cfPassword))

    {

        // Username and password are valid!!

    }


    CFRelease(cfUsername);

    CFRelease(idArray);

    CFRelease(cfPassword);

    CFRelease(query);

}


查看完整回答
反对 回复 2022-05-10
  • 1 回答
  • 0 关注
  • 108 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信