ASP.NET で、IIS 5.0/6.0 と SQL Server が異なるマシンのときに
ADO.NET の接続文字列を以下のように記述して
Dim cn As New SqlConnection("Server=xxx;Trusted_Connection=true;")
または
Dim cn As New SqlConnection("Server=xxx;Integrated Security=SSPI;")
SQL Server に対して Windows 認証(NTLM 認証)で接続しようと
した場合に発生するエラーについての話です。
# 以前に GDNJ に投稿した内容と関連情報をまとめてみました。
■ デフォルト設定の場合
IIS: 匿名アクセスを有効
ASP.NET: 偽装を無効(impersonate="false")
ADO.NET: Network Library に TCP/IP ソケットを利用
SQL Server: Windows 認証モードで動作
デフォルトでは、表題と同じ以下のエラーが表示されます。
ユーザー '(null)' のログインに失敗しました。
理由 : SQL Server の信頼関係接続に関連付けられていません。
(null) という表現は、単に認証が失敗して「不明なユーザー」
という意味で使われています (ログインを試みたユーザー名
がエラーに表示されると親切なのですが...)。
また、信頼関係接続という言葉は、SQL Server では古くから
使われていて、Trusted Connection を訳したものです。
つまり、Windows 認証接続という意味です。
・Network Library に"名前付きパイプ"を利用した場合
ADO.NET の接続文字列に Network Library=dbnmpntw を追加して
名前付きパイプを使うようにすると、エラーメッセージが以下の
ように代わりますが、エラーの意味は TCP/IP ソケットのときと同じです。
SQL Server が存在しないか、アクセスが拒否されました。
・Windows 認証に失敗する理由
デフォルトでは、ASP.NET のワーカープロセスの実行アカウント
が SQL Server への Windows ログインを試みます。
このアカウントは、IIS のバージョンによって異なり、
IIS 5.0: ASPNET
IIS 6.0: NT AUTHORITY\Network Service
です。ワーカープロセスは、それぞれ
IIS 5.0: aspnet_wp.exe
IIS 6.0: w3wp.exe
という名前なので、タスクマネージャの[プロセス]タブで
ユーザー名を表示すれば、実行アカウントを確認できます。
Windows 認証に失敗する理由は、「ASPNET」と「Network Service」
アカウントのパスワードが、自動的に管理されており、マシンが異なる
と違うものが設定されるためです。したがって、SQL Server 側に同じ
ユーザーが存在したとしてもパスワードが異なることになり、
Windows 認証が失敗することになります。
・エラーの回避方法
エラーの回避方法はいくつかあるのですが、IIS 6.0 の場合に
一番簡単なのは、同じユーザー名/パスワードのアカウントを
IIS と SQL Server 上に登録し、それをワーカープロセスの実行
アカウントに設定するという方法です。
これは、PASSJ 掲示板に投稿した以下の記事が参考になると思います。
http://www.sqlpassj.org/bbs/bbs_disp.aspx?forum_id=1¤t_page=1&disp_mode=2&detail_mode=1&message_id=1094
・IIS 5.0 の場合
IIS 5.0 ではワーカープロセスの実行アカウントを変更する
方法は面倒なので、偽装を使う方法が簡単でお勧めです。
具体的には、以下のように操作します。
1. IIS と SQL Server 上に同じユーザー名/パスワードのアカウントを作成
2. Web.Config ファイルで偽装(impersonate)を有効(true)
に設定し(デフォルトは false)、1 で作成したユーザー、パスワード
を userName、password に指定する。
<identity impersonate="true" userName="ユーザー名" password="パスワード" />
3. 1 で作成したユーザーに NTFS アクセス権の「読み取り」を付与する
■ IIS で Windows 認証(NTLM 認証)、ダブルホップ偽装ができない問題
IIS: Windows 認証
ASP.NET: 偽装を有効(impersonate="true")
SQL Server: Windows 認証モードで動作
このように IIS 側で Windows 認証を利用する場合は、
いくつか注意点があります。
・Windows 認証されたユーザーに NTFS アクセス権の「読み取り」が付与されてない場合
NTFS アクセス権がない場合は、IIS 側でアクセス拒否されてしまいます。
(匿名アクセスが有効な場合は、匿名ユーザーとして扱われます)。
・IIS と同じマシンの IE から接続する場合
これは、開発環境などで IIS と同じマシン上からアクセスを試す場合の話です。
この場合は、Windows へログオンしたユーザーが SQL Server へのログインを試み、
SQL Server 側の権限が設定されていれば何の問題もなくアクセス可能です。
・IIS とは異なるマシンから接続する場合
これは、本番環境を想定してクライアントマシンから IIS へアクセスする場合の話です。
この場合は、以下のエラーメッセージが表示されます。
エラーの詳細をリモート表示できません
デフォルトでは、リモートマシンからはエラーの詳細を確認できないので
これが発生します。エラーを表示するには、Web.Config で
<customErrors mode="Off" />
と設定します。
設定後、もう一度アクセスすると、表題と同じ以下のエラーが表示されます。
ユーザー '(null)' のログインに失敗しました。
理由 : SQL Server の信頼関係接続に関連付けられていません。
これは、NTLM 認証がダブルホップ偽装(2段階の偽装)をサポートして
いないために発生するエラーです。
この問題については、TechEd 2002 Yokohama での NEC 吉田薫さん(MVP for Security)
のセッション「5-329 IIS による認証と承認の実現」でとても分かりやすく説明されて
いるのでカンファレンス CD をお持ちの方は、ご覧になることをお勧めします。
また、この問題の回避方法については、以下の GDNJ 掲示板に
投稿した記事が参考になると思います。
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=2149
NTLM 認証については、以下の @IT の記事で分かりやすく書かれています。
@ITハイブックス連携企画 > Windows サーバー セキュリティ徹底解説
第5章 内部ネットワークレイヤの保護 (Windows Server 2003の認証システム)
http://www.atmarkit.co.jp/fsecurity/hybooks/win_server_sec/wss01-01.html
<その他の参考資料>
・GDNJ: SQLサーバーへの接続エラー
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=11302
・[INFO] IIS におけるブラウザ クライアントの認証方法
http://support.microsoft.com/?id=264921
・ASP.NET における認証 : .NET セキュリティ ガイド
http://www.eu.microsoft.com/japan/msdn/net/bda/authaspdotnet.asp
・ASP.NET + IIS 6 のセキュリティ モデル - デモ解説
http://www.gotdotnet.com/team/ja/team/fieldevangelists/kenjikat/B301demo.aspx
・DBマガジン 2004年2月号 「IIS徹底攻略」
・GDNJ: IIS6.0でのASP.NETのクライアント偽装
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=8799
・GDNJ: ダブルホップ問題?
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=8276
・[HOWTO] ASP.NET で System.DirectoryServices 名前空間を使用する方法
http://support.microsoft.com/?id=329986
・[PRB] ASP/ODBC/SQL Server エラー 0x80040E4D "ユーザー '(Null)' のログインに失敗しました"
http://support.microsoft.com/?id=307002
以下、似たような内容ばかりですが、備忘録として...
・[ASP] 名前付きパイプを使ったMicrosoft SQLサーバーへの接続方法
http://support.microsoft.com/?id=410763
・[HOWTO] 認証を委任する場合の ASP.NET アプリケーションの構成方法
http://support.microsoft.com/?id=810572
・[HOW TO] 名前付きパイプを経由した Microsoft SQL Server への接続
http://support.microsoft.com/?id=159976
・PRB: ASP から SQL Server に接続するとき、エラー メッセージ
http://support.microsoft.com/?id=253500
・[IIS] Active Server Pages からユーザーを偽装する方法
http://support.microsoft.com/?id=248187
・[INFO] ASP.NET アプリケーションに偽装を実装する
http://support.microsoft.com/?id=306158
・[HOW TO] Windows セキュリティを使用して ASP.NET アプリケーションをセキュリティで保護する方法
http://support.microsoft.com/?id=315736