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

标签 macos go authentication operating-system

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

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

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

编辑

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

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

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。

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

最佳答案

a solution in C or C++ would be useful too



这是使用 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);
}

关于macos - 如何以编程方式在 macOS 上验证用户和密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59956598/

相关文章:

ios - NEHotspotHelper:无法在身份验证状态机的身份验证状态下发送 Web 请求

node.js - 在单元测试中模拟 Passport.js(本地策略)

windows - 与 PhoneGap 紧密相关的桌面发布平台?

macos - 如何在 Cocoa WebView 中编辑所选文本的字体、大小和颜色

go - 如何获取有关 Go 中最后调用的函数的信息?

c - 为什么我不能从 Golang 中正确读取 C 常量?

ios - NSTextStorage 语法 Markdown

macos - Haskell 包缺少 c 库

reflection - 如何在 go 中嵌入默认实现并引用嵌入类型

iphone - 如何显示登录和关闭设置 - Storyboard