Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Fügen Sie moderne Authentifizierung zu Ihren ASP.NET MVC- und Web-API-Anwendungen auf .NET Framework 4.7.2+ hinzu, indem Sie das Microsoft.Identity.Web.OWIN-Paket verwenden.
Grundlegendes zur OWIN-Integration
Das Microsoft.Identity.Web.OWIN Paket bringt die Leistungsfähigkeit von Microsoft.Identity.Web zu ASP.NET MVC und Web-API-Anwendungen, die die OWIN-Middleware mit Microsoft Entra ID verwenden.
Überprüfen der wichtigsten Vorteile
In der folgenden Tabelle sind die wichtigsten Features und Vorteile des Pakets zusammengefasst.
| Funktion | Nutzen |
|---|---|
| TokenAcquirerFactory | Automatische Tokenerfassung mit Zwischenspeicherung |
| Controllererweiterungen | Einfacher Zugriff auf GraphServiceClient und IDownstreamApi |
| Verteilter Token-Cache | Integrierte Unterstützung für SQL Server, Redis, Cosmos DB, PostgreSQL |
| Automatische Tokenaktualisierung | Verarbeitet die Tokenaktualisierung transparent |
| Inkrementelle Zustimmung | Nahtlose Integration des Zustimmungsflusses |
Überprüfen unterstützter Szenarien
Microsoft. Identity.Web.OWIN unterstützt die folgenden Anwendungstypen und Szenarien.
- ASP.NET MVC Webanwendungen (.NET Framework 4.7.2+)
- ASP.NET-Web-API (.NET Framework 4.7.2+)
- Hybrid-Apps (MVC + Web-API)
- Microsoft Graph aufrufen aus Controllern
- Aufrufen nachgeschalteter APIs mit automatischer Authentifizierung
Installiere das Paket
Installieren Sie das Microsoft.Identity.Web.OWIN-NuGet-Paket mit Ihrer bevorzugten Methode.
Führen Sie den folgenden Befehl in der konsole Paket-Manager aus:
Install-Package Microsoft.Identity.Web.OWIN
Führen Sie alternativ den folgenden Befehl mit der .NET CLI aus:
dotnet add package Microsoft.Identity.Web.OWIN
Abhängigkeiten werden automatisch eingeschlossen:
- Microsoft.Identity.Web.TokenAcquisition
- Microsoft. Identity.Web.TokenCache
- Microsoft.Owin
- System.Web
Konfigurieren der Anwendung
Konfigurieren Sie Ihre Anwendungseinstellungen, um eine Verbindung mit Microsoft Entra- und downstream-APIs herzustellen.
Konfigurieren von Web.config
Fügen Sie der datei Web.config die folgenden Microsoft Entra- und downstream-API-Einstellungen hinzu.
<configuration>
<appSettings>
<!-- Microsoft Entra ID Configuration -->
<add key="AzureAd:Instance" value="https://login.microsoftonline.com/" />
<add key="AzureAd:TenantId" value="your-tenant-id" />
<add key="AzureAd:ClientId" value="your-client-id" />
<add key="AzureAd:ClientSecret" value="your-client-secret" />
<add key="AzureAd:RedirectUri" value="https://localhost:44368/" />
<add key="AzureAd:PostLogoutRedirectUri" value="https://localhost:44368/" />
<!-- Microsoft Graph Configuration -->
<add key="DownstreamApi:MicrosoftGraph:BaseUrl" value="https://graph.microsoft.com/v1.0" />
<add key="DownstreamApi:MicrosoftGraph:Scopes" value="user.read" />
<!-- Custom Downstream API Configuration -->
<add key="DownstreamApi:TodoListService:BaseUrl" value="https://localhost:44351" />
<add key="DownstreamApi:TodoListService:Scopes" value="api://todo-api-client-id/.default" />
</appSettings>
<connectionStrings>
<!-- Optional: SQL Server Token Cache -->
<add name="TokenCache"
connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TokenCache;Integrated Security=True;" />
</connectionStrings>
</configuration>
Konfigurieren von appsettings.json (Alternative)
Sie können einstellungen auch in einer appsettings.json Datei speichern, wie im folgenden Beispiel gezeigt.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"RedirectUri": "https://localhost:44368/",
"PostLogoutRedirectUri": "https://localhost:44368/"
},
"DownstreamApi": {
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
},
"TodoListService": {
"BaseUrl": "https://localhost:44351",
"Scopes": "api://todo-api-client-id/.default"
}
}
}
Einrichten der Startklasse
Registrieren Sie Authentifizierungs-Middleware, Tokenakquisition und nachgeschaltete API-Dienste in Ihrer Startklasse.
Konfigurieren von App_Start/Startup.Auth.cs
Der folgende Code zeigt ein vollständiges Setup mit Microsoft. Identity.Web.OWIN:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Microsoft.Identity.Web.TokenCacheProviders.Distributed;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using System;
using System.Configuration;
using System.Web;
namespace MyMvcApp
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Set default authentication type
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
// Configure cookie authentication
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "MyApp.Auth",
ExpireTimeSpan = TimeSpan.FromHours(1),
SlidingExpiration = true
});
// Configure OpenID Connect authentication
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = ConfigurationManager.AppSettings["AzureAd:ClientId"],
Authority = $"https://login.microsoftonline.com/{ConfigurationManager.AppSettings["AzureAd:TenantId"]}",
RedirectUri = ConfigurationManager.AppSettings["AzureAd:RedirectUri"],
PostLogoutRedirectUri = ConfigurationManager.AppSettings["AzureAd:PostLogoutRedirectUri"],
Scope = "openid profile email offline_access",
ResponseType = "code id_token",
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
NameClaimType = "preferred_username"
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
// Configure Microsoft Identity Web services
var services = CreateOwinServiceCollection();
// Add token acquisition
services.AddTokenAcquisition();
// Add Microsoft Graph support
services.AddMicrosoftGraph();
// Add downstream API support
services.AddDownstreamApi("MicrosoftGraph", services.BuildServiceProvider()
.GetRequiredService<IConfiguration>().GetSection("DownstreamApi:MicrosoftGraph"));
services.AddDownstreamApi("TodoListService", services.BuildServiceProvider()
.GetRequiredService<IConfiguration>().GetSection("DownstreamApi:TodoListService"));
// Configure token cache (choose one option)
ConfigureTokenCache(services);
// Build service provider
var serviceProvider = services.BuildServiceProvider();
// Create and register token acquirer factory
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Build(serviceProvider);
// Add OWIN token acquisition middleware
app.Use<OwinTokenAcquisitionMiddleware>(tokenAcquirerFactory);
}
private IServiceCollection CreateOwinServiceCollection()
{
var services = new ServiceCollection();
// Add configuration from appsettings.json and/or Web.config
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddInMemoryCollection(new Dictionary<string, string>
{
["AzureAd:Instance"] = ConfigurationManager.AppSettings["AzureAd:Instance"],
["AzureAd:TenantId"] = ConfigurationManager.AppSettings["AzureAd:TenantId"],
["AzureAd:ClientId"] = ConfigurationManager.AppSettings["AzureAd:ClientId"],
["AzureAd:ClientSecret"] = ConfigurationManager.AppSettings["AzureAd:ClientSecret"],
["DownstreamApi:MicrosoftGraph:BaseUrl"] = ConfigurationManager.AppSettings["DownstreamApi:MicrosoftGraph:BaseUrl"],
["DownstreamApi:MicrosoftGraph:Scopes"] = ConfigurationManager.AppSettings["DownstreamApi:MicrosoftGraph:Scopes"],
})
.Build();
services.AddSingleton(configuration);
return services;
}
private void ConfigureTokenCache(IServiceCollection services)
{
// Option 1: In-memory cache (development)
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedMemoryCache();
});
// Option 2: SQL Server cache (production)
/*
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = ConfigurationManager.ConnectionStrings["TokenCache"].ConnectionString;
options.SchemaName = "dbo";
options.TableName = "TokenCache";
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
});
*/
// Option 3: Redis cache (production, high-scale)
/*
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddStackExchangeRedisCache(options =>
{
options.Configuration = ConfigurationManager.AppSettings["Redis:ConnectionString"];
options.InstanceName = "MyMvcApp_";
});
});
*/
}
}
}
Integrieren von Controllern
Greifen Sie mithilfe der vom Paket bereitgestellten Erweiterungsmethoden auf Microsoft Graph und downstream-APIs von Ihren Controllern zu.
Integrieren von MVC-Controllern
Das folgende Beispiel zeigt, wie Controllererweiterungsmethoden für den Zugriff auf Microsoft Graph verwendet werden:
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Microsoft.Graph;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace MyMvcApp.Controllers
{
[Authorize]
public class HomeController : Controller
{
// GET: Home/Index
public async Task<ActionResult> Index()
{
try
{
// Access Microsoft Graph using extension method
var graphClient = this.GetGraphServiceClient();
var user = await graphClient.Me.GetAsync();
ViewBag.UserName = user.DisplayName;
ViewBag.Email = user.Mail ?? user.UserPrincipalName;
ViewBag.JobTitle = user.JobTitle;
return View();
}
catch (MsalUiRequiredException)
{
// Incremental consent required
return new ChallengeResult();
}
catch (Exception ex)
{
return View("Error", new ErrorViewModel { Message = ex.Message });
}
}
// GET: Home/Profile
public async Task<ActionResult> Profile()
{
var graphClient = this.GetGraphServiceClient();
// Get user profile
var user = await graphClient.Me
.GetAsync(requestConfig => requestConfig.QueryParameters.Select = new[] { "displayName", "mail", "jobTitle", "department" });
return View(user);
}
// GET: Home/Photo
public async Task<ActionResult> Photo()
{
var graphClient = this.GetGraphServiceClient();
try
{
// Get user photo
var photoStream = await graphClient.Me.Photo.Content.GetAsync();
return File(photoStream, "image/jpeg");
}
catch (ServiceException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return File(Server.MapPath("~/Content/images/default-user.png"), "image/png");
}
}
}
}
Integrieren von Web-API-Controllern
Das folgende Beispiel zeigt, wie ApiController-Erweiterungsmethoden zum Aufrufen einer downstream-API verwendet werden:
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Microsoft.Identity.Abstractions;
using System.Threading.Tasks;
using System.Web.Http;
namespace MyWebApi.Controllers
{
[Authorize]
[RoutePrefix("api/todos")]
public class TodoController : ApiController
{
// GET: api/todos
[HttpGet]
[Route("")]
public async Task<IHttpActionResult> GetTodos()
{
try
{
// Call downstream API using extension method
var downstreamApi = this.GetDownstreamApi();
var todos = await downstreamApi.GetForUserAsync<List<TodoItem>>(
"TodoListService",
options =>
{
options.RelativePath = "api/todolist";
});
return Ok(todos);
}
catch (MsalUiRequiredException)
{
return Unauthorized();
}
catch (HttpRequestException ex)
{
return InternalServerError(ex);
}
}
// POST: api/todos
[HttpPost]
[Route("")]
public async Task<IHttpActionResult> CreateTodo([FromBody] TodoItem todo)
{
var downstreamApi = this.GetDownstreamApi();
var createdTodo = await downstreamApi.PostForUserAsync<TodoItem, TodoItem>(
"TodoListService",
todo,
options =>
{
options.RelativePath = "api/todolist";
});
return Created($"api/todos/{createdTodo.Id}", createdTodo);
}
}
}
Microsoft Graph aufrufen
Verwenden Sie GraphServiceClient, um mit Microsoft Graph-Daten von Ihren Controllern zu interagieren.
Einrichten des Microsoft Graph-Clients
Der Microsoft Graph-Client ist bereits in Startup.Auth.cs mit folgendem Aufruf konfiguriert:
services.AddMicrosoftGraph();
Verwenden von GraphServiceClient in Controllern
Im folgenden Beispiel werden allgemeine Microsoft Graph Vorgänge in einem MVC-Controller veranschaulicht.
[Authorize]
public class GraphController : Controller
{
public async Task<ActionResult> MyProfile()
{
var graphClient = this.GetGraphServiceClient();
var user = await graphClient.Me.GetAsync();
return View(user);
}
public async Task<ActionResult> MyManager()
{
var graphClient = this.GetGraphServiceClient();
var manager = await graphClient.Me.Manager.GetAsync();
return View(manager);
}
public async Task<ActionResult> MyDirectReports()
{
var graphClient = this.GetGraphServiceClient();
var directReports = await graphClient.Me.DirectReports.GetAsync();
return View(directReports.Value);
}
public async Task<ActionResult> SendEmail([FromBody] EmailMessage message)
{
var graphClient = this.GetGraphServiceClient();
var email = new Message
{
Subject = message.Subject,
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = message.Body
},
ToRecipients = new[]
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = message.To
}
}
}
};
await graphClient.Me.SendMail.PostAsync(new SendMailPostRequestBody
{
Message = email
});
return RedirectToAction("Index");
}
}
Aufrufen nachgeschalteter APIs
Registrieren und aufrufen nachgeschalteter APIs mit automatischer Tokenakquisition von Ihren Controllern.
Konfigurieren der downstream-API
Registrieren Sie die Downstream-API im Startup.Auth.cs im folgenden Code:
services.AddDownstreamApi("TodoListService", configuration.GetSection("DownstreamApi:TodoListService"));
Fügen Sie die entsprechenden Einstellungen hinzu in Web.config:
<add key="DownstreamApi:TodoListService:BaseUrl" value="https://localhost:44351" />
<add key="DownstreamApi:TodoListService:Scopes" value="api://todo-api-client-id/.default" />
Verwenden von IDownstreamApi in Controllern
Das folgende Beispiel zeigt, wie CRUD-Vorgänge für eine downstream-API von einem MVC-Controller ausgeführt werden.
[Authorize]
public class TodoController : Controller
{
// GET all todos
public async Task<ActionResult> Index()
{
var downstreamApi = this.GetDownstreamApi();
var todos = await downstreamApi.GetForUserAsync<List<TodoItem>>(
"TodoListService",
options =>
{
options.RelativePath = "api/todolist";
});
return View(todos);
}
// GET specific todo
public async Task<ActionResult> Details(int id)
{
var downstreamApi = this.GetDownstreamApi();
var todo = await downstreamApi.GetForUserAsync<TodoItem>(
"TodoListService",
options =>
{
options.RelativePath = $"api/todolist/{id}";
});
return View(todo);
}
// POST new todo
[HttpPost]
public async Task<ActionResult> Create(TodoItem todo)
{
var downstreamApi = this.GetDownstreamApi();
var createdTodo = await downstreamApi.PostForUserAsync<TodoItem, TodoItem>(
"TodoListService",
todo,
options =>
{
options.RelativePath = "api/todolist";
});
return RedirectToAction("Index");
}
// PUT update todo
[HttpPost]
public async Task<ActionResult> Edit(int id, TodoItem todo)
{
var downstreamApi = this.GetDownstreamApi();
await downstreamApi.CallApiForUserAsync(
"TodoListService",
options =>
{
options.HttpMethod = HttpMethod.Put;
options.RelativePath = $"api/todolist/{id}";
options.RequestBody = todo;
});
return RedirectToAction("Index");
}
// DELETE todo
[HttpPost]
public async Task<ActionResult> Delete(int id)
{
var downstreamApi = this.GetDownstreamApi();
await downstreamApi.CallApiForUserAsync(
"TodoListService",
options =>
{
options.HttpMethod = HttpMethod.Delete;
options.RelativePath = $"api/todolist/{id}";
});
return RedirectToAction("Index");
}
}
Erkunden von Beispielanwendungen
Verwenden Sie die folgenden Beispiele, um Microsoft.Identity.Web.OWIN in Aktion zu sehen.
Überprüfen der offiziellen Microsoft Beispiele
In der folgenden Tabelle sind offizielle Beispiele aufgeführt, die die Integration von Microsoft.Identity.Web.OWIN veranschaulichen.
| Beispiel | Beschreibung |
|---|---|
| ms-identity-aspnet-webapp-openidconnect | ASP.NET MVC-App mit Microsoft. Identity.Web.OWIN |
| Schlüsseldateien |
App_Start/Startup.Auth.cs, Controllers/HomeController.cs |
Klonen Sie das Beispiel, und führen Sie es mit den folgenden Befehlen aus:
git clone https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect
cd ms-identity-aspnet-webapp-openidconnect
# Update Web.config with your Microsoft Entra app registration
# Run in Visual Studio
Bewährte Methoden befolgen
Wenden Sie diese empfohlenen Muster an, und vermeiden Sie häufige Fehler beim Erstellen mit Microsoft. Identity.Web.OWIN.
Empfohlene Muster anwenden
1. Verwenden Sie verteilten Cache in der Produktion:
// Production
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = ConfigurationManager.ConnectionStrings["TokenCache"].ConnectionString;
options.SchemaName = "dbo";
options.TableName = "TokenCache";
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
});
2. Behandeln Sie die inkrementelle Zustimmung ordnungsgemäß:
try
{
var graphClient = this.GetGraphServiceClient();
var user = await graphClient.Me.GetAsync();
}
catch (MsalUiRequiredException)
{
// User needs to consent to additional scopes
return new ChallengeResult();
}
3. Verwenden Sie Korrelations-IDs für die Problembehandlung:
var downstreamApi = this.GetDownstreamApi();
var correlationId = Guid.NewGuid();
var result = await downstreamApi.GetForUserAsync<Todo>(
"TodoListService",
options =>
{
options.RelativePath = $"api/todolist/{id}";
options.TokenAcquisitionOptions = new TokenAcquisitionOptions
{
CorrelationId = correlationId
};
});
4. Implementieren Sie die richtige Fehlerbehandlung:
try
{
// Call API
}
catch (MsalUiRequiredException)
{
return new ChallengeResult();
}
catch (HttpRequestException ex)
{
logger.Error($"API call failed: {ex.Message}");
return View("Error");
}
Vermeiden häufiger Fehler
1. Verwenden Sie keinen Speichercache für Webfarmen:
// Wrong for load-balanced scenarios
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedMemoryCache();
});
// Correct
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedSqlServerCache(/* ... */);
});
2. Keine hartcodierte Konfiguration:
// Wrong
ClientId = "your-client-id-here"
// Correct
ClientId = ConfigurationManager.AppSettings["AzureAd:ClientId"]
3. Nicht den Ablauf von Tokens ignorieren:
// Microsoft.Identity.Web.OWIN handles this automatically
// No manual token refresh needed!
Häufige Probleme beheben
Überprüfen Sie die folgenden Lösungen für häufige Probleme, die während des Setups und der Laufzeit auftreten.
Allgemeine Probleme beheben
Problem 1: "IAuthorizationHeaderProvider kann nicht gefunden werden"
Lösung: Stellen Sie sicher, dass OwinTokenAcquirerFactory in Startup.Auth.cs registriert ist:
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Build(serviceProvider);
app.Use<OwinTokenAcquisitionMiddleware>(tokenAcquirerFactory);
Problem 2: "GraphServiceClient konnte nicht gefunden werden"
Lösung: Fügen Sie AddMicrosoftGraph() in Startup.Auth.cs hinzu:
services.AddMicrosoftGraph();
Problem 3: Tokencache wird nicht beibehalten
Lösung: Überprüfen der Konfiguration des verteilten Caches:
services.AddDistributedTokenCaches(cacheServices =>
{
cacheServices.AddDistributedSqlServerCache(options =>
{
// Ensure connection string is correct
options.ConnectionString = ConfigurationManager.ConnectionStrings["TokenCache"].ConnectionString;
});
});
Durchsuchen verwandter Inhalte
Erfahren Sie mehr über verwandte Features und Szenarien.