by WebSurfer
20. January 2014 16:36
ASP.NET Web Forms アプリケーションの Page 内では、以下の 3 つのプロパティ/メソッドで ID オブジェクト(WindowsIdentity または GenericIdentity)を取得できます。
それぞれどのように違うかを調べましたので、備忘録として書いておきます。
HttpRequest.LogonUserIdentity
現在 IIS が HTTP 要求を受けているユーザーの WindowsIdentity(Windows ユーザーを表す)オブジェクトを取得します。
匿名アクセス(Page.User.Identity.IsAuthenticated が false)の場合は常に IUSR となります。IUSR とは、匿名認証が有効化されている場合は常に IIS によって使用される既定の ID です。
ログイン済みユーザー(Page.User.Identity.IsAuthenticated が true)の場合は認証方式によって異なり、以下の通りとなります。
-
フォーム認証:ワーカープロセス(例:IIS7 では NETWORK SERVICE)
-
Windows 認証:ログインユーザーの Windows アカウント
ASP.NET 偽装の有効・無効には影響を受けず、常に上記の通りとなります。
WindowsIdentity.GetCurrent
ASP.NET 偽装が無効になっている場合は、ワーカープロセスを実行しているアカウント(IIS7 では NETWORK SERVICE)の WindowsIdentity オブジェクトを取得します。
ASP.NET 偽装が有効になっている場合は、偽装の設定方法、認証方式、匿名アクセスかログイン済みかによって、取得される WindowsIdentity オブジェクトは異なります(「偽装」しているだけで、実際にワーカープロセスを実行しているアカウントは変わらないのかもしれません・・・未確認です)。
web.config での偽装の設定を、単純に <identity impersonate="true" /> とした場合には以下のようになります。
フォーム認証
-
匿名アクセス:IUSR
-
ログイン済み:ワーカープロセス(例:IIS7 では NETWORK SERVICE)
Windows 認証
-
匿名アクセス:IUSR
-
ログイン済み:ログインユーザーの Windows アカウント
上記の偽装の設定に userName 属性、password 属性の設定を追加し、特定の Windows ユーザーアカウントを偽装した場合は、認証方式や認証済みか否かに関わらず、常に userName 属性に設定したユーザーアカウントになります。
Page.User.Identity
現在ページ要求を行っているユーザーを表す ID オブジェクトを取得します。
Page.User プロパティは、Windows 認証が有効になっている場合は WindowsPrincipal を、Windows 認証が無効の場合は RolePrincipal(ロール メンバシップを含む現在の HTTP 要求のセキュリティ情報)を取得します。
そして、WindowsPrincipal.Identity からは WindowsIdentity オブジェクトが、RolePrincipal.Identity からは GenericIdentity(標準ユーザーを表す)が取得されます。
ただし、それらの中身は ASP.NET が書き換えており、特に Name は、匿名アクセスの場合は IUSR ではなく空文字になること、フォーム認証のログイン済みユーザーの場合は Windows アカウント名ではなくフォーム認証のユーザー ID となる点に注意してください。
具体的には、IsAuthenticated, AuthenticationType, Name プロパティは以下の通りとなります。
フォーム認証、匿名アクセス
-
IsAuthenticated: false
-
AuthenticationType:(空文字)
-
Name:(空文字)
フォーム認証、ログイン済み
-
IsAuthenticated: true
-
AuthenticationType: Forms
-
Name: フォーム認証のユーザー ID
Windows 認証、匿名アクセス
-
IsAuthenticated: false
-
AuthenticationType:(空文字)
-
Name:(空文字)
Windows 認証、ログイン済み
-
IsAuthenticated: true
-
AuthenticationType: Negotiate
-
Name: ログインユーザーの Windows アカウント
by WebSurfer
4. September 2010 20:01
Visual Studio のウィサードを使うと、SQL Server や Access のテーブルを表示して、レコードを INSERT, DELETE, UPDATE するプログラムが簡単に作れます。
ただし、Access でオートナンバー(SQL Server で言うと IDENTITY)を使っている場合、INSERT した時に DB 側で設定したオートナンバー値を DataSet に書き込むところまでは面倒を見てくれません。(SQL Server の場合は面倒見てくれます)
これは、JET データベースエンジン(Microsoft Access およびその他の小規模アプリケーションで使用されている)では、単一バッチで複数のステートメントを実行できないということが理由のようです。
詳しくは、MSDN ライブラリの @@IDENTITY クライシスを管理する の「Microsoft Access/JET の問題」のセクションを参照してください。
ここでは、DataAdapter の RowUpdated イベントを使用して自動生成されたコードとは別のクエリを実行し、オートナンバー値を DataSet に書き込む具体的な例を紹介します。
まず、いつもの手順で型付 DataSet を作り、データソースウィンドウからテーブルを Form にドラッグ&ドロップしてアプリケーションを作ります。以下の画像がその例です。ここまではコードは一行も書く必要がありません。
ただし、ここまでの実装では、新しいレコードを INSERT したとき、オートナンバーとなっている ID の値が DataSet に書き戻されていないので、DataGridView に表示されている ID 値は正しくありません。
そこで、INSERT 直後に発生する DataAdapter の RowUpdated イベントのハンドラで、"SELECT @@IDENTITY" クエリを使って新規 ID 値を取得し、それを DataSet に書き込んでやります。
具体的には、TableAdapter を partial class を使って拡張します。ソリューションにクラスファイルを追加して、以下のようなコードを実装します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace AccessWithAutoNumberAndDataSet.DataSet1TableAdapters
{
public partial class XXXTableAdapter
{
public void SetHandler()
{
this.Adapter.RowUpdated +=
new OleDbRowUpdatedEventHandler(Adapter_RowUpdated);
}
private OleDbCommand cmd =
new OleDbCommand("SELECT @@IDENTITY", null);
private void Adapter_RowUpdated(Object sender, OleDbRowUpdatedEventArgs e)
{
cmd.Connection = e.Command.Connection;
cmd.Transaction = e.Command.Transaction;
if (e.StatementType == StatementType.Insert &&
e.Status == UpdateStatus.Continue)
{
object obj = cmd.ExecuteScalar();
if (obj != null && obj.GetType() != typeof(DBNull))
{
e.Row["ID"] = (int)obj;
e.Row.AcceptChanges();
}
}
}
}
}
これだけでは、ハンドラがイベントにアタッチされてい���いので、自動生成された Form のコードのコンストラクタに、上記 partial class で定義した SetHandler メソッドを追記します。以下のような感じです。
namespace AccessWithAutoNumberAndDataSet
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// これを追加。
this.xXXTableAdapter.SetHandler();
}
これで、新規 ID 値が DataSet に書き込まれ、DataGridView に表示されるようになります。