かなり単純なことをする必要があります。ASP.NET MVC アプリケーションで、カスタムの IIdentity / IPrincipal を設定します。どちらが簡単か、より適切か。 および のようなものを呼び出せるように、デフォルトを拡張します。User.Identity.Id
特別User.Identity.Role
なことは何もなく、いくつかの追加プロパティがあるだけです。
たくさんの記事や質問を読みましたが、実際よりも難しくしている気がします。簡単だと思っていました。ユーザーがログオンしたら、カスタム IIdentity を設定したいのです。そこで、Application_PostAuthenticateRequest
global.asax に実装しようと思いました。しかし、これはすべてのリクエストで呼び出され、すべてのリクエストでデータベースへの呼び出しを行いたくありません。データベースからすべてのデータを要求し、カスタム IPrincipal オブジェクトに配置することになります。これも非常に不必要で、遅く、間違った場所 (そこでデータベース呼び出しを行う) にあるように思えますが、私が間違っている可能性があります。あるいは、そのデータは他にどこから来るのでしょうか?
そこで、ユーザーがログインするたびに、セッションに必要な変数をいくつか追加し、それをApplication_PostAuthenticateRequest
イベント ハンドラーのカスタム IIdentity に追加できると考えました。ただし、my はそこにContext.Session
あるnull
ため、これも適切な方法ではありません。
私はこれに 1 日取り組んできましたが、何かが足りない気がします。これはそれほど難しいことではないはずですよね? また、これに付随する (半) 関連のものすべてに少し混乱しています。、、、、、、、、MembershipProvider
...。これらすべてが非常に混乱していると思うのは私だけでしょうか?MembershipUser
RoleProvider
ProfileProvider
IPrincipal
IIdentity
FormsAuthentication
誰かが、余分な煩わしさなしに IIdentity に追加データを格納するためのシンプルでエレガント、かつ効率的なソリューションを教えてくれたら、それは素晴らしいことです。SO に同様の質問があることは知っていますが、必要な答えがそこにあったら、私は見落としているに違いありません。
ベストアンサー1
やり方は次のとおりです。
IIdentity と IPrincipal の両方を実装する必要がなくなるため、IIdentity の代わりに IPrincipal を使用することにしました。
インターフェースを作成する
interface ICustomPrincipal : IPrincipal { int Id { get; set; } string FirstName { get; set; } string LastName { get; set; } }
カスタムプリンシパル
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; } }
LogIn メソッド - カスタム情報を含む Cookie の設定
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>
ビューでは次のようにアクセスできます。
@User.FirstName
@User.LastName