我目前正在使用 Net5.0 Web 应用程序解决类似的问题。它似乎在本地工作的原因是您使用可以访问 Azure SQL 的用户登录到 Visual Studio,这些是您在 Db 中获得的权限。IDE 使用这些凭据代替托管服务标识,后者在您将应用程序上传到 Azure 时使用。
如您所述,在应用程序注册中,您需要为 Azure SQL 数据库 user_impersonation 应用程序授予权限。
在您的代码中,您需要从https://database.windows.net//.default请求一个令牌(注意 // v1 端点需要它)。通过引用 /.default,您要求您在应用注册门户中为应用选择的所有权限。
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#the-default-scope
在 Startup.cs 中,您需要在所需范围内启用 EnableTokenAcquisitionToCallDownstreamApi。
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(new[]
{"https://database.windows.net//.default"})
// Adds the User and App InMemory Token Cache
.AddInMemoryTokenCaches();
services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the
// default policy
options.FallbackPolicy = options.DefaultPolicy;
});
services.AddDbContext<MyDatabaseContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyAzureConnection")));
// The database interface
services.AddScoped<ITodos, TodoData>();
services.AddRazorPages()
.AddRazorRuntimeCompilation()
.AddMvcOptions(o =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
o.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();
您还需要使用控制器来装饰控制器[AuthorizeForScopes(Scopes = new string[]{"https://database.windows.net//.default"}]
并包含该控制器所需的范围。对于 Razor,它位于页面模型的顶部,需要引用“使用 Microsoft.Identity.Web;”
namespace ToDoApp.Pages.Todos
{
[AuthorizeForScopes(ScopeKeySection = "AzureSQL:BaseUrl")]
public class CreateModel : PageModel
我在 appsettings.json 中使用一个部分作为范围并使用以下方法检索它ScopeKeySection
:
"AzureSQL": {
"BaseUrl": "https://database.windows.net//.default",
"Scopes": "user_impersonation"
}
这向您展示了将它包含在 MVC、Razor 和 Blazor 的位置:
https://github.com/AzureAD/microsoft-identity-web/wiki/Managing-incremental-consent-and-conditional-access#in-mvc-controllers
最后,您的 DbContext 需要一个令牌,您可以将其从客户端应用程序(也许......)传递给它。
这就是我现在的做法
public class MyDatabaseContext : DbContext
{
private readonly ITokenAcquisition _tokenAcquisition;
public MyDatabaseContext (ITokenAcquisition tokenAcquisition,
DbContextOptions<MyDatabaseContext> options)
: base(options)
{
_tokenAcquisition = tokenAcquisition;
string[] scopes = new[]{"https://database.windows.net//.default"};
var result = _tokenAcquisition.GetAuthenticationResultForUserAsync(scopes)
.GetAwaiter()
.GetResult();
token = result.AccessToken;
var connection = (SqlConnection)Database.GetDbConnection();
connection.AccessToken = result.token;
}
这是一个有缺陷的解决方案。如果我重新启动应用程序并尝试再次访问它,我会收到错误消息Microsoft.Identity.Web.MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user
它似乎与TokenCache有关。如果我退出并再次登录或清除我的浏览器缓存,错误就会得到解决。我有一个解决方法可以在失败时登录应用程序,但由于我使用的是应用程序的凭据,所以它有缺陷。
但是,它以用户而不是具有用户权限的应用程序成功连接到 Azure SQL Db。当我解决错误(或找到错误)时,我将更新此答案。