GRPC 中的驗證和授權 ASP.NET CoreAuthentication and authorization in gRPC for ASP.NET Core

James 牛頓By James Newton-King

查看或下載範例程式碼 (如何下載) View or download sample code (how to download)

驗證呼叫 gRPC 服務的使用者Authenticate users calling a gRPC service

gRPC 可搭配 ASP.NET Core authentication 使用,以將使用者與每個呼叫產生關聯。gRPC can be used with ASP.NET Core authentication to associate a user with each call.

以下是 Startup.Configure 使用 gRPC 和 ASP.NET Core authentication 的範例:The following is an example of Startup.Configure which uses gRPC and ASP.NET Core authentication:

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();
    
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>();
    });
}

注意

您註冊 ASP.NET Core authentication 中介軟體重要的順序。The order in which you register the ASP.NET Core authentication middleware matters. 一律 UseAuthentication 在前後 UseAuthorization 呼叫 UseRouting UseEndpointsAlways call UseAuthentication and UseAuthorization after UseRouting and before UseEndpoints.

需要設定您的應用程式在呼叫期間使用的驗證機制。The authentication mechanism your app uses during a call needs to be configured. 會在中新增驗證設定 Startup.ConfigureServices ,並且會根據您的應用程式所使用的驗證機制而有所不同。Authentication configuration is added in Startup.ConfigureServices and will be different depending upon the authentication mechanism your app uses. 如需如何保護 ASP.NET Core 應用程式的範例,請參閱 驗證範例For examples of how to secure ASP.NET Core apps, see Authentication samples.

設定好驗證之後,即可透過 gRPC 服務方法存取使用者 ServerCallContextOnce authentication has been setup, the user can be accessed in a gRPC service methods via the ServerCallContext.

public override Task<BuyTicketsResponse> BuyTickets(
    BuyTicketsRequest request, ServerCallContext context)
{
    var user = context.GetHttpContext().User;

    // ... access data from ClaimsPrincipal ...
}

持有人權杖驗證Bearer token authentication

用戶端可以提供存取權杖來進行驗證。The client can provide an access token for authentication. 伺服器會驗證權杖,並使用它來識別使用者。The server validates the token and uses it to identify the user.

在伺服器上,會使用 JWT 持有人中介軟體來設定持有人權杖驗證。On the server, bearer token authentication is configured using the JWT Bearer middleware.

在 .NET gRPC 用戶端中,您可以使用集合以呼叫傳送權杖 MetadataIn the .NET gRPC client, the token can be sent with calls by using the Metadata collection. 集合中的專案 Metadata 會以 gRPC 呼叫作為 HTTP 標頭來傳送:Entries in the Metadata collection are sent with a gRPC call as HTTP headers:

public bool DoAuthenticatedCall(
    Ticketer.TicketerClient client, string token)
{
    var headers = new Metadata();
    headers.Add("Authorization", $"Bearer {token}");

    var request = new BuyTicketsRequest { Count = 1 };
    var response = await client.BuyTicketsAsync(request, headers);

    return response.Success;
}

ChannelCredentials在通道上設定是使用 gRPC 呼叫將權杖傳送給服務的另一種方式。Configuring ChannelCredentials on a channel is an alternative way to send the token to the service with gRPC calls. ChannelCredentials可以包含 CallCredentials ,以提供自動設定的方式 MetadataA ChannelCredentials can include CallCredentials, which provide a way to automatically set Metadata.

CallCredentials 會在每次進行 gRPC 呼叫時執行,這樣可避免需要在多個位置撰寫程式碼來自行傳遞權杖。CallCredentials is run each time a gRPC call is made, which avoids the need to write code in multiple places to pass the token yourself. 請注意, CallCredentials 只有在使用 TLS 保護通道時,才會套用。Note that CallCredentials are only applied if the channel is secured with TLS. CallCredentials 不會套用到不安全的非 TLS 通道。CallCredentials aren't applied on unsecured non-TLS channels.

下列範例中的認證會設定通道,以使用每個 gRPC 呼叫來傳送權杖:The credential in the following example configures the channel to send the token with every gRPC call:

private static GrpcChannel CreateAuthenticatedChannel(string address)
{
    var credentials = CallCredentials.FromInterceptor((context, metadata) =>
    {
        if (!string.IsNullOrEmpty(_token))
        {
            metadata.Add("Authorization", $"Bearer {_token}");
        }
        return Task.CompletedTask;
    });

    // SslCredentials is used here because this channel is using TLS.
    // CallCredentials can't be used with ChannelCredentials.Insecure on non-TLS channels.
    var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
    {
        Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
    });
    return channel;
}

用戶端憑證驗證Client certificate authentication

用戶端也可以提供用戶端憑證來進行驗證。A client could alternatively provide a client certificate for authentication. 憑證驗證 會在 TLS 層級進行,但在達到 ASP.NET Core 之前也是如此。Certificate authentication happens at the TLS level, long before it ever gets to ASP.NET Core. 當要求進入 ASP.NET Core 時, 用戶端憑證驗證封裝 可讓您將憑證解析為 ClaimsPrincipalWhen the request enters ASP.NET Core, the client certificate authentication package allows you to resolve the certificate to a ClaimsPrincipal.

注意

將伺服器設定為接受用戶端憑證。Configure the server to accept client certificates. 如需在 Kestrel、IIS 和 Azure 中接受用戶端憑證的相關資訊,請參閱 在 ASP.NET Core 中設定憑證驗證For information on accepting client certificates in Kestrel, IIS, and Azure, see 在 ASP.NET Core 中設定憑證驗證.

在 .NET gRPC 用戶端中,會將用戶端憑證新增至 HttpClientHandler 之後用來建立 gRPC 用戶端的憑證:In the .NET gRPC client, the client certificate is added to HttpClientHandler that is then used to create the gRPC client:

public Ticketer.TicketerClient CreateClientWithCert(
    string baseAddress,
    X509Certificate2 certificate)
{
    // Add client cert to the handler
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(certificate);

    // Create the gRPC channel
    var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
    {
        HttpHandler = handler
    });

    return new Ticketer.TicketerClient(channel);
}

其他驗證機制Other authentication mechanisms

許多 ASP.NET Core 支援的驗證機制可與 gRPC 搭配運作:Many ASP.NET Core supported authentication mechanisms work with gRPC:

  • Azure Active DirectoryAzure Active Directory
  • 用戶端憑證Client Certificate
  • Identity伺服器IdentityServer
  • JWT 權杖JWT Token
  • OAuth 2.0OAuth 2.0
  • OpenID ConnectOpenID Connect
  • WS-同盟WS-Federation

如需在伺服器上設定驗證的詳細資訊,請參閱 ASP.NET Core authenticationFor more information on configuring authentication on the server, see ASP.NET Core authentication.

將 gRPC 用戶端設定為使用驗證將取決於您所使用的驗證機制。Configuring the gRPC client to use authentication will depend on the authentication mechanism you are using. 先前的持有人權杖和用戶端憑證範例顯示了幾種方法,可讓您使用 gRPC 呼叫來設定 gRPC 用戶端傳送驗證中繼資料:The previous bearer token and client certificate examples show a couple of ways the gRPC client can be configured to send authentication metadata with gRPC calls:

  • 強型別 gRPC 用戶端會 HttpClient 在內部使用。Strongly typed gRPC clients use HttpClient internally. 您可以在 HttpClientHandler上設定驗證,或將自訂 HttpMessageHandler 實例加入至 HttpClientAuthentication can be configured on HttpClientHandler, or by adding custom HttpMessageHandler instances to the HttpClient.
  • 每個 gRPC 呼叫都有一個選擇性 CallOptions 引數。Each gRPC call has an optional CallOptions argument. 您可以使用選項的標頭集合來傳送自訂標頭。Custom headers can be sent using the option's headers collection.

注意

Windows 驗證 (NTLM/Kerberos/Negotiate) 無法與 gRPC 搭配使用。Windows Authentication (NTLM/Kerberos/Negotiate) can't be used with gRPC. gRPC 需要 HTTP/2,而 HTTP/2 不支援 Windows 驗證。gRPC requires HTTP/2, and HTTP/2 doesn't support Windows Authentication.

授權使用者存取服務和服務方法Authorize users to access services and service methods

根據預設,服務中的所有方法都可由未經驗證的使用者呼叫。By default, all methods in a service can be called by unauthenticated users. 若要要求驗證,請將 [Authorize] 屬性套用至服務:To require authentication, apply the [Authorize] attribute to the service:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}

您可以使用屬性的函式引數和屬性, [Authorize] 將存取限制為僅符合特定 授權原則的使用者。You can use the constructor arguments and properties of the [Authorize] attribute to restrict access to only users matching specific authorization policies. 例如,如果您有一個名為的自訂授權原則 MyAuthorizationPolicy ,請確定只有符合該原則的使用者可以使用下列程式碼來存取服務:For example, if you have a custom authorization policy called MyAuthorizationPolicy, ensure that only users matching that policy can access the service using the following code:

[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}

個別的服務方法也可以套用 [Authorize] 屬性。Individual service methods can have the [Authorize] attribute applied as well. 如果目前使用者不符合 同時 套用至方法和類別的原則,則會將錯誤傳回給呼叫者:If the current user doesn't match the policies applied to both the method and the class, an error is returned to the caller:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
    public override Task<AvailableTicketsResponse> GetAvailableTickets(
        Empty request, ServerCallContext context)
    {
        // ... buy tickets for the current user ...
    }

    [Authorize("Administrators")]
    public override Task<BuyTicketsResponse> RefundTickets(
        BuyTicketsRequest request, ServerCallContext context)
    {
        // ... refund tickets (something only Administrators can do) ..
    }
}

其他資源Additional resources