基于令牌的数据库身份验证失败,用户" NT AUTHORITY \ ANONYMOUS LOGON'登录失败。"。

时间:2018-02-01 10:35:58

标签: azure authentication azure-sql-database azure-active-directory adal

我在使用基于令牌的数据库身份验证时遇到问题。使用Active Directory密码连接有效,但在连接令牌时收到以下错误:

  用户' NT AUTHORITY \ ANONYMOUS LOGON&#39>

登录失败。

此问题已在here on Stack Overflowhere on MSDN中讨论过,但没有可用的解决方案。 This blog post表示用户权限存在问题,但相当模糊。

配置

使用以下方法获取令牌成功:

static async Task<string> GetAccessToken()
{
    var certificateSDN = "redacted";
    var tenantId = "redacted";
    var clientId = "redacted";
    var resource = "https://database.windows.net";

    X509Certificate2 certificate;
    using (var certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
    {
        certificateStore.Open(OpenFlags.ReadOnly);
        certificate = certificateStore.Certificates
            .Find(X509FindType.FindBySubjectDistinguishedName, certificateSDN, false)
            [0];
    }

    var authenticationContext = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}");
    var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);
    var authenticationResult = await authenticationContext.AcquireTokenAsync(resource, clientAssertionCertificate);

    return authenticationResult.AccessToken;
}

连接数据库的方式如下:

var connectionStringBuilder = new SqlConnectionStringBuilder()
{
    DataSource = "redacted.database.windows.net",
    InitialCatalog = "redacted",
};
using (var sqlConnection = new SqlConnection(connectionStringBuilder.ConnectionString))
{
    sqlConnection.AccessToken = accessToken;
    sqlConnection.Open();
}

调用sqlConnection.Open()时出错。

clientId与应用注册的应用ID相匹配。我已在数据库中创建了一个用户,该应用程序注册的名称与以下查询匹配:

create user [redacted] from external provider
go
exec sp_addrolemember N'db_datareader', N'redacted'
exec sp_addrolemember N'db_datawriter', N'redacted'

诊断

通过以下查询,我检查用户是否具有角色并具有连接数据库的权限:

declare @user nvarchar(max);
set @user = 'redacted'

select
    u.name
    ,r.name
from
    sys.database_role_members as m
    inner join sys.database_principals as r on m.role_principal_id = r.principal_id
    inner join sys.database_principals as u on u.principal_id = m.member_principal_id
where
    u.name = @user;

select
    class_desc
    ,major_id
    ,permission_name
    ,state_desc
from
    sys.database_permissions
where
    grantee_principal_id = user_id(@user);

这是输出:

redacted    db_datareader
redacted    db_datawriter

DATABASE    0   CONNECT GRANT

尝试连接虚假令牌会产生同样的错误。因此,我不知道我的令牌是否有问题,或者数据库配置是否有问题。我可以执行哪些其他诊断,找到导致此问题的原因?

1 个答案:

答案 0 :(得分:7)

结果证明这是一个非常小的错误:resource最后需要一个最后的斜杠。

所以而不是

var resource = "https://database.windows.net";

它需要

var resource = "https://database.windows.net/";