[解決済み] ASP.NET MVC - カスタムIIdentityまたはIPrincipalの設定
質問
ASP.NET MVCアプリケーションで、カスタムのIIdentity/IPrincipalを設定したいのですが、簡単なことでしょうか?どちらか簡単な方、またはより適切な方。私は、デフォルトを拡張して、次のようなものを呼び出すことができるようにしたい。
User.Identity.Id
と
User.Identity.Role
. 何も派手なことはせず、いくつかのプロパティを追加しただけです。
大量の記事や質問を読みましたが、実際より難しくしているような気がします。私はそれが簡単だと思った。ユーザーがログオンした場合、私はカスタムIIdentityを設定したいと思います。だから、私は実装しようと思いました
Application_PostAuthenticateRequest
をglobal.asaxに追加しました。しかし、それはすべてのリクエストで呼び出されます。そして、私はすべてのリクエストでデータベースへの呼び出しを行い、データベースからすべてのデータを要求し、カスタムIPrincipalオブジェクトを置くことはしたくありません。それはまた、非常に不必要で、遅く、間違った場所(そこでデータベースを呼び出すこと)にあるように思えますが、私は間違っているかもしれません。また、そのデータはどこから来るのでしょうか?
そこで私は、ユーザーがログインするたびに、必要な変数をセッションに追加し、その変数を
Application_PostAuthenticateRequest
イベントハンドラです。しかし、私の
Context.Session
は
null
があるので、それもNGです。
1日前から作業しているのですが、何か足りないような気がします。これって、そんなに難しくないはずですよね?また、これに付随する(半)関連事項にも少し戸惑っています。
MembershipProvider
,
MembershipUser
,
RoleProvider
,
ProfileProvider
,
IPrincipal
,
IIdentity
,
FormsAuthentication
.... このようなことを考えると、とても混乱するのは私だけでしょうか?
IIdentityに余分なデータを保存するための、シンプルでエレガントで効率的な解決策を教えてもらえたら、とても嬉しいです。SOに似たような質問があるのは知っていますが、もし私が必要とする答えがそこにあるのなら、私は見落としていたに違いありません。
どのように解決するのですか?
以下はその方法です。
IIdentityの代わりにIPrincipalを使うことにしたのは、IIdentityとIPrincipalの両方を実装する必要がないためだ。
-
インターフェイスの作成
interface ICustomPrincipal : IPrincipal { int Id { get; set; } string FirstName { get; set; } string LastName { get; set; } }
-
CustomPrincipal
public class CustomPrincipal : ICustomPrincipal { public IIdentity Identity { get; private set; } public bool IsInRole(string role) { return false; } public CustomPrincipal(string email) { this.Identity = new GenericIdentity(email); } public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
-
CustomPrincipalSerializeModel - FormsAuthenticationTicketオブジェクトのuserdataフィールドにカスタム情報をシリアライズするためのモデルです。
public class CustomPrincipalSerializeModel { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
-
ログイン方法 - カスタム情報を含むクッキーの設定
if (Membership.ValidateUser(viewModel.Email, viewModel.Password)) { var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First(); CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel(); serializeModel.Id = user.Id; serializeModel.FirstName = user.FirstName; serializeModel.LastName = user.LastName; JavaScriptSerializer serializer = new JavaScriptSerializer(); string userData = serializer.Serialize(serializeModel); FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket( 1, viewModel.Email, DateTime.Now, DateTime.Now.AddMinutes(15), false, userData); string encTicket = FormsAuthentication.Encrypt(authTicket); HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket); Response.Cookies.Add(faCookie); return RedirectToAction("Index", "Home"); }
-
Global.asax.cs - クッキーを読み込んで、HttpContext.Userオブジェクトを置き換える、これはPostAuthenticateRequestをオーバーライドすることによって行われる
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) { HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie != null) { FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); JavaScriptSerializer serializer = new JavaScriptSerializer(); CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData); CustomPrincipal newUser = new CustomPrincipal(authTicket.Name); newUser.Id = serializeModel.Id; newUser.FirstName = serializeModel.FirstName; newUser.LastName = serializeModel.LastName; HttpContext.Current.User = newUser; } }
-
Razorのビューでのアクセス
@((User as CustomPrincipal).Id) @((User as CustomPrincipal).FirstName) @((User as CustomPrincipal).LastName)
とコードで表示します。
(User as CustomPrincipal).Id
(User as CustomPrincipal).FirstName
(User as CustomPrincipal).LastName
このコードは自明だと思います。そうでない場合は、教えてください。
さらに、アクセスをより簡単にするために、ベースコントローラを作成し、返されたUserオブジェクト(HttpContext.User)をオーバーライドすることができます。
public class BaseController : Controller
{
protected virtual new CustomPrincipal User
{
get { return HttpContext.User as CustomPrincipal; }
}
}
とし、各コントローラーごとに
public class AccountController : BaseController
{
// ...
}
を使用すると、このようなコードでカスタムフィールドにアクセスできるようになります。
User.Id
User.FirstName
User.LastName
しかし、これはビューの中では動作しません。そのためには、カスタムのWebViewPageの実装を作成する必要があります。
public abstract class BaseViewPage : WebViewPage
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
Views/web.configでデフォルトのページタイプにする。
<pages pageBaseType="Your.Namespace.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
で、viewsでは、このようにアクセスします。
@User.FirstName
@User.LastName
関連
-
.NET 6:.NETのロギングコンポーネントlog4netを使用する。
-
net core downlink tracking skywalking インストールと使いやすいチュートリアル
-
403 - アクセス拒否。IIS7 でファイルを開くと、アクセス拒否されます。
-
[解決済み] ファイルアップロード ASP.NET MVC 3.0
-
[解決済み] ASP.NET MVCでenumからドロップダウンリストを作成するにはどうすればよいですか?
-
[解決済み] ASP.NET MVCでビューをコンパイルする
-
[解決済み] ASP.NET MVCコントローラは、Imageを返すことができますか?
-
[解決済み】ASP.NET MVC 4でカスタムエラーページを動作させる方法
-
[解決済み] ASP.Net MVCとWebフォームを比較する最大のメリット
-
[解決済み] フォーム認証のタイムアウトとsessionStateのタイムアウトの比較
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
.netcoreプロジェクトでIStartupFilterを使用するためのチュートリアル
-
.NET 6:.NETのロギングコンポーネントlog4netを使用する。
-
NETガベージコレクション GC診断ツール dotnet-gcmon 使用方法
-
ASP.NET CoreでURLを設定する5つの方法
-
ASP.NET Coreミドルウェアによるグローバル例外処理機構の利用について
-
Net CoreによるAutoFacの利用
-
[解決済み] Server Error in '/' Application」エラーの解決方法を教えてください。
-
[解決済み] IIS Expressのweb.configにMIMEマッピングを追加する
-
[解決済み] フォーム認証のタイムアウトとsessionStateのタイムアウトの比較
-
[解決済み] コンテンツ」項目が重複して含まれていました。.NET SDKは、デフォルトでプロジェクトディレクトリの'Content'アイテムを含めます。