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

use*_*702 3 authentication azure azure-active-directory adal azure-sql-database

我无法获得基于令牌的数据库身份验证.使用Active Directory密码连接有效,但在与令牌连接时,我收到以下错误:

用户'NT AUTHORITY\ANONYMOUS LOGON'登录失败.

此问题已在Stack Overflow此处的MSDN 进行了讨论,但没有可用的解决方案.这篇博客文章表明用户权限有问题,但它相当含糊.

组态

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

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;
}
Run Code Online (Sandbox Code Playgroud)

连接到数据库的方式如下:

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

调用时发生错误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'
Run Code Online (Sandbox Code Playgroud)

诊断

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

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);
Run Code Online (Sandbox Code Playgroud)

这是输出:

redacted    db_datareader
redacted    db_datawriter

DATABASE    0   CONNECT GRANT
Run Code Online (Sandbox Code Playgroud)

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

use*_*702 8

事实证明这是一个非常小的错误:resource最后需要一个最后的斜线.

而不是

var resource = "https://database.windows.net";
Run Code Online (Sandbox Code Playgroud)

它需要

var resource = "https://database.windows.net/";
Run Code Online (Sandbox Code Playgroud)

  • 关闭一个[字符]错误...让我疯了.这次真是万分感谢; 它也解决了我的问题 (3认同)