ASP.NET MVC - 認証リファクタリング
-
16-09-2019 - |
質問
このコードで私が見た問題は、それが頻繁に再利用されることです。認証されたユーザー (サイト管理者を除く) によって編集/作成されるものはすべて、そのユーザーの「スタジオ」オブジェクトにのみアクセスできます。
皆さんへの質問です。サービス層をクライアントの知識から切り離して抽象化するには、これをどのようにリファクタリングしますか。後でスタンドアロンのデスクトップ アプリケーションでサービス層を再利用するつもりです。
私の間違ったやり方に光を当ててください!大変感謝しております。
AuthorizeOwnerAttribute.cs (認可属性)
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// Get the authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = httpContext.Request.Cookies[cookieName];
// If the cookie can't be found, don't issue the ticket
if (authCookie == null) return false;
// Get the authentication ticket and rebuild the principal & identity
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] userData = authTicket.UserData.Split(new[] { '|' });
int userId = Int32.Parse(userData[0]);
int studioID = Int32.Parse(userData[1]);
GenericIdentity userIdentity = new GenericIdentity(authTicket.Name);
WebPrincipal userPrincipal = new WebPrincipal(userIdentity, userId, studioID);
httpContext.User = userPrincipal;
return true;
}
「ユーザー」コントローラー内で、所有者を必要とするメソッドにこの属性をアタッチします。
[AuthorizeOwner]
public ActionResult Edit(int Id)
{
IUser user = userService.GetById(HttpContext.User, Id);
return View(user);
}
さて、サービス層では、渡された IPrincipal がリクエストされているオブジェクトにアクセスできるかどうかを確認しています。 ここから臭くなってきます。
ユーザーサービス.cs
public IUser GetById(IPrincipal authUser, int id)
{
if (authUser == null) throw new ArgumentException("user");
WebPrincipal webPrincipal = authUser as WebPrincipal;
if (webPrincipal == null) throw new AuthenticationException("User is not logged in");
IUser user = repository.GetByID(id).FirstOrDefault();
if (user != null)
{
if (user.StudioID != webPrincipal.StudioID) throw new AuthenticationException("User does not have ownership of this object");
return user;
}
throw new ArgumentException("Couldn't find a user by the id specified", "id");
}
解決
実際の ID を Cookie に保存するかどうかはわかりません。少し公開されすぎます。私は、セッション ハッシュを使用してデータを保存し、サーバー上にデータを保持し、公開されないようにしたいと考えています。
また、(ユーザー ID を渡すことによって) モデルを使用して、どのオブジェクトを返すかを決定します。一致するスタジオIDを持つもの。そうすれば、コントローラーは「GetObjects(int id)」を呼び出すだけで済みます。コントローラーが何もアクセスできない場合は、null または空のコレクションが返されます。そのほうが私にとってはすっきりした気がします。
所属していません StackOverflow