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

我有一个应用程序询问用户的用户名和密码。目前,对于 Unix 系统(大多数),我从中读取密码哈希,/etc/shadow但对于 macOS 来说更麻烦(他们使用自己的标准),所以我想知道是否有一种简单的方法来验证用户名和密码。


我正在考虑login以一种奇怪的方式使用该程序,但这不是最好的解决方案。


我正在使用 golang,但 C 或 C++ 中的解决方案也会很有用。


编辑


@TheNextman 的答案正是我所要求的,但与其他人交谈时,他们建议我使用 PAM,因为它适用于多个操作系统。我花了一些精力来理解它,因为我正在寻找一个简单的 API 来验证用户和密码,verify(username string, password string) -> boolean但我知道 PAM 更通用,因此更复杂。


但这是我最终使用的代码,它是在 GO 中使用 C 绑定制作的。


package Authentication

import "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.GoString

func (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。


但总的来说,我认为这是一个强大的解决方案,因为我正在重用现有的身份验证机制。


哆啦的时光机
浏览 109回答 1
1回答

大话西游666

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);}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go