認証はどのIDがSQL Serverに接続するかを確立します。 データベースの権限は、接続後にそのアイデンティティが何をできるかを決定します。 アプリケーションが動作する環境の認証を選択し、 トランスポート層セキュリティ(TLS)暗号化と証明書検証 を独立して設定してください。
SQL Serverのサーバー認証モードは、クライアントが送信する認証情報とは異なります:
- Windows 認証 モードはWindowsの識別子を受け入れます。
- ミックスモードはWindowsのIDとSQL Serverのユーザー名およびパスワードを受け入れます。
クライアントの接続文字列を設定しても、サーバーの認証モードは変わりません。 サーバー設定については「 認証モードの選択」を参照してください。
認証シナリオ
環境が対応している場合は、アプリケーション管理パスワードを必要としない認証を好みます。
| アプリケーション環境 | 認証の選択 |
|---|---|
| 適切なWindowsアイデンティティを持つドメイン環境。 |
Integrated Security=true。 SQL Serverは信頼できる環境内の別のコンピュータに設置可能です。 |
| 設定済みドメインアイデンティティを使用するLinuxまたはmacOSアプリケーション。 | クライアントとサーバーの両方でKerberosの前提条件を統合したセキュリティ。 |
| LocalDBを用いたWindowsのローカル開発。 | ローカル開発者のアイデンティティに基づく統合セキュリティ。 |
| Azureホスト型アプリケーションで、SQLエンドポイントでMicrosoft Entraサポートがあります。 | マネージドIDや他の適切なMicrosoft Entra認証モード。 |
| SQL認証情報が必要な環境。 | 保護された構成や秘密ストアから取得する、最も権限の低い認証情報を用いたSQL認証。 |
インターネット向けのアプリケーションは本質的にSQL認証を必要としません。 ウェブユーザーのサインインとアプリケーションのデータベース識別は別々の決定です。
Windows 認証と接続してください
アプリケーションが動作する識別子を使いましょう:
Server=tcp:<server>,1433;Database=<database>;Integrated Security=true;Encrypt=true;TrustServerCertificate=false;MultiSubnetFailover=true;
Trusted_Connection=true は Integrated Security=true のシノニムです。 統合セキュリティを有効にすると、接続文字列内のUser IDやPasswordは無視されます。 別のWindowsユーザーを選ぶわけではありません。
サービスは通常、そのウェブインターフェースを使う人としてではなく、サービスアイデンティティとして接続します。 意図したサービス識別子にデータベース権限を付与します。 エンドユーザーの身元を複数のコンピュータ間で委任する必要がある場合は、Kerberosの委任を明示的に設定・レビューしてください。
プラットフォームの前提条件
| Client | 要件と動作 |
|---|---|
| Windowsの.NETフレームワーク。 | ネイティブのWindowsネットワークとセキュリティサポートプロバイダーインターフェース(SSPI)を使用しています。 |
| Windowsのモダン.NET。 | デフォルトでネイティブネットワークを使用しています。 Windows Negotiateは設定時にKerberosを選択します。NT LAN Manager(NTLM)にフォールバックできます。 |
| LinuxやmacOSでのモダン.NET。 | マネージドネットワーキングと.NET NegotiateAuthenticationを使用しています。 Kerberosクライアント、領域、サービスプリンシパル名(SPN)、有効な認証情報またはチケットキャッシュを設定してください。 |
統合されたセキュリティは、ドメイントラストの設定、ドメインネームシステム(DNS)解決、時間同期、SQL Server SPNの設定の代わりにはなりません。 Linuxでは、アプリケーションを起動する前に、 kinitなどのKerberosツールでチケットを取得してください。 WindowsのNTLMフォールバックがWindows以外のクライアントで利用できるとは限りません。
Kerberos接続についてはSPN登録を参照してください。
現在のSQL Server接続の認証方式を確認するには、以下の Transact-SQL(T-SQL)クエリを実行します:
SELECT auth_scheme
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;
この診断ビューへのアクセスはサーバーの権限に依存します。 成功した接続だけでは、NTLMではなくケルベロスが使われたとは限りません。
セキュリティコンテキスト交渉を制御する必要があるアプリケーションでは、 SspiContextProvider カスタムSSPI実装をサポートしています。 これはカスタムKerberosや明示的なNTLM認証情報などのシナリオにおける高度な拡張ポイントです。 これは接続文字列認証モードではなく、 AccessToken や AccessTokenCallbackと組み合わせることもできません。
カスタムセキュリティサポートプロバイダーインターフェース(SSPI)コンテキストプロバイダー
SspiContextProvider抽象クラスはすべてのSSPIコンテキストプロバイダーの基盤です。 カスタムプロバイダーを作成するには、SspiContextProvider を継承し、GenerateContext メソッドをオーバーライドしてください。 接続を開く前に、SspiContextProvider の SqlConnection プロパティにプロバイダーのインスタンスを割り当ててください。
GenerateContextメソッドはSSPI認証ハンドシェイク時に呼び出されます。 サーバーから送信された認証ブロブ、送信される応答ブロブ用のバッファライター、次のような接続メタデータを含む SspiAuthenticationParameters オブジェクトを受け取ります:
-
Resource- サーバーのサービスプリンシパル名(SPN) -
ServerName- データ ソースの名前。 -
DatabaseName- 指定されている場合のターゲットデータベース。 -
UserId- 接続文字列で指定されている場合のユーザーID。 -
Password- 接続文字列で指定されている場合のパスワード。
重要な考慮事項:
- 接続を開ける前に
SspiContextProviderプロパティを設定してください。 オープン接続または接続中の接続に設定しようとすると、InvalidOperationExceptionが発生します。 -
SspiContextProviderインスタンスは接続プールを識別するために使われるキーの一部です。 各SqlConnectionごとに新しいSspiContextProviderインスタンスを作成するのは避けてください。新しいプロバイダーごとに新しいプールが作成されるためです。 プーリングの対象とする接続については、同じプロバイダーのインスタンスを参照してください。 - カスタム
SspiContextProviderは、同じ入力パラメーターに対して同じセキュリティ コンテキストで認証される必要があります。 セキュリティコンテキストが異なる場合、誤ったセキュリティコンテキストのプール接続が接続要求に対して返されることがあります。 -
SspiContextProviderはトークンベースの認証と相互排他的です。AccessTokenやAccessTokenCallbackと併用すると、どちらのプロパティを先に設定してもInvalidOperationExceptionが発生します。
Example
NegotiateAuthentication は .NET 7 以降を必要とするため、この例は .NET Framework 上でコンパイルできません。 .NET Framework プロバイダーの場合は、代わりにプラットフォームの SSPI API に対して GenerateContext を実装してください。
以下の例は、認証を行うために NegotiateAuthentication を用いるカスタムSSPIコンテキストプロバイダーを示しています。
using System;
using System.Buffers;
using System.Net.Security;
using Microsoft.Data.SqlClient;
class CustomSspiContextProvider : SspiContextProvider
{
private NegotiateAuthentication? _auth;
protected override bool GenerateContext(
ReadOnlySpan<byte> incomingBlob,
IBufferWriter<byte> outgoingBlobWriter,
SspiAuthenticationParameters authParams)
{
_auth ??= new NegotiateAuthentication(
new NegotiateAuthenticationClientOptions
{
Package = "Negotiate",
TargetName = authParams.Resource,
});
byte[]? blob = _auth.GetOutgoingBlob(
incomingBlob, out NegotiateAuthenticationStatusCode statusCode);
if (statusCode is not NegotiateAuthenticationStatusCode.Completed
and not NegotiateAuthenticationStatusCode.ContinueNeeded)
{
return false;
}
if (blob is not null)
{
outgoingBlobWriter.Write(blob);
}
return true;
}
}
プロバイダーを接続に割り当ててから、その接続を開きます:
using var connection = new SqlConnection(
"Server=myServer;Database=myDatabase;Integrated Security=true;Encrypt=True;");
connection.SspiContextProvider = new CustomSspiContextProvider();
connection.Open();
セキュリティに関する考慮事項
カスタムSSPIコンテキストプロバイダーを実装する際には、以下のセキュリティ上の考慮事項を念頭に置いてください:
-
すべての入力を検証してください。
処理前に必ず入ってくるブロブと認証パラメータを検証してください。 形式に誤りがあるデータや予期しないデータについては、
GenerateContextからfalseを返して拒否する必要があります。 -
認証情報を保護する。
SspiAuthenticationParametersオブジェクトにはUserIdやPasswordなどの機微な値が含まれている場合があります。 これらの値を安全でない方法で記録したり、永続させたり、送信したりしないでください。 - 実績のある認証ライブラリを使用してください。 可能な限り、暗号プロトコルを自分で実装するのではなく、認証ロジックを NegotiateAuthentication のような十分にテストされたライブラリに委ねてください。
-
リソースの破棄。
プロバイダーが管理対象外のリソースまたは認証コンテキストを割り当てる場合は、IDisposableを実装し、適切なクリーンアップを行うようにしてください。 SqlClientは
SspiContextProviderインスタンスを破棄しません。 アプリケーションでプロバイダーが不要になった場合は、プロバイダーを破棄してください。 -
認証パッケージを制限してください。
環境に適した認証パッケージ(例:
NegotiateやKerberos)のみを使用してください。 信頼できる入力と設定だけを認証パッケージに渡します。 - 徹底的にテストしてください。 トークン更新、接続プーリング、フェイルオーバーシナリオなど、すべての予想される条件下でプロバイダーが正しく動作しているか確認してください。
Microsoft はカスタムSspiContextProvider実装の検証や監査は行わず、カスタムプロバイダーを通じて認証された接続の安全性も保証しません。 カスタム実装によって生じた脆弱性はあなたの責任です。
ログインの種類
ログインするとサーバーへのIDアクセス権が与えられます。 データベースユーザーはデータベース内のアイデンティティを表します。 意図したログインやグループをデータベースユーザーにマッピングし、必要な権限だけをデータベースロールを通じて付与します。
SQL ServerはWindowsアカウントログイン、Windowsグループログイン、SQLログインをサポートしています。 Windowsグループでは、管理者が各人ごとに別々のSQL Serverログインを作成することなくメンバーシップを管理できます。 コード署名に使われる証明書や非対称鍵のログインは、インタラクティブな接続識別子ではありません。
含まれるデータベースユーザーとMicrosoft Entraプリンシパルは異なるプロビジョニング要件を持っています。 すべてのユーザーがSQLログインを必要としていると仮定するのではなく、 プリンシパル やエンドポイントの認証ドキュメントを確認してください。
混合モード認証
SQL認証は、それを受け入れるよう設定されたエンドポイントでのみ使用してください。
User IDとPasswordを供給し、統合セキュリティを無効にし、証明書検証を有効にしたままにしてください。
Authentication=Sql Password明示的にSQLパスワード認証を選択しています。Microsoft Entraパスワード認証を選択しません。
以下の.NETコンソールの例はMicrosoft.Data.SqlClientを使用しています。 開発環境や秘密注入メカニズムを通じて SQL_SERVER、 SQL_DATABASE、 SQL_USER_ID、 SQL_PASSWORD を設定しましょう。
SQL_SERVER
tcp:sql-server.contoso.com,1433のような伝送制御プロトコル(TCP)エンドポイントを含むべきです。 パスワードや完了した接続文字列は印刷しないでください。
using Microsoft.Data.SqlClient;
static string Required(string name) =>
Environment.GetEnvironmentVariable(name)
?? throw new InvalidOperationException($"Set {name} before running.");
var options = new SqlConnectionStringBuilder
{
DataSource = Required("SQL_SERVER"),
InitialCatalog = Required("SQL_DATABASE"),
Authentication = SqlAuthenticationMethod.SqlPassword,
UserID = Required("SQL_USER_ID"),
Password = Required("SQL_PASSWORD"),
Encrypt = SqlConnectionEncryptOption.Mandatory,
TrustServerCertificate = false,
MultiSubnetFailover = true
};
using var connection = new SqlConnection(options.ConnectionString);
await connection.OpenAsync();
using var command = new SqlCommand("SELECT DB_NAME();", connection);
Console.WriteLine(await command.ExecuteScalarAsync());
クエリは接続されたデータベース名を印刷します。 認証情報を文字列に連結する代わりに SqlConnectionStringBuilder を使うのが良いでしょう。 ビルダーは接続文字列の値をエスケープします。どのサーバー、データベース、またはアプリケーションが許可すべき権限を決めるわけではありません。
Persist Security Info=false続けてください。それがデフォルトです。 生産の秘密は保護された秘密ストアに保存し、誰が読めるかを制限し、ローテーションします。 通常のアプリケーションリクエストには管理者やデータベース所有者のアイデンティティを使用しないでください。
Microsoft Entraとサービスの制限
Integrated Security=trueWindowsのアイデンティティをSQL Serverに認証します。
Authentication=Active Directory IntegratedMicrosoft Entraトークンを取得します。 これらは互換性があるわけではありません。
Azure SQL Databaseは通常のWindows統合認証ではなく、SQLまたはMicrosoft Entra認証を使用しています。 Microsoft FabricのSQLデータベースはMicrosoft Entraの識別子のみをサポートしており、SQL認証やログインはサポートされていません。 トークンベースの接続についてはMicrosoft Entraの記事を活用してください。