私たちには多数のコントローラがあり、ログインページ以外のすべてのコントローラとそのアクションに適用されるグローバルフィルタを作成するのが理想的です。カスタムASP.NET MVCフォーム認証
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e) // Code that runs on application startup
{
... // only showing important part
GlobalFilters.Filters.Add(new Filters.AuthenticationUserActionFilter());
...
}
ファイルAuthenticationUserActionFilter.cs
:
はGlobal.asax.csでは、私は次のグローバルフィルタを追加
public class AuthorizeUserActionFilter : System.Web.Mvc.Filters.IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousActionFilter), inherit: true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousActionFilter), inherit: true);
if (skipAuthorization) // anonymous filter attribute in front of controller or controller method
return;
// does this always read value from ASPXAUTH cookie ?
bool userAuthenticated = filterContext.HttpContext.User.Identity.IsAuthenticated;
if (!userAuthenticated)
{
filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary() { { "controller", "Account" }, { "action", "Login" } });
return;
}
if(HttpContext.Current.User as Contracts.IUser == null)
{
// check if IUser is stored in session otherwise retrieve from db
// System.Web.HttpContext.Current.User is reseted on every request.
// Is it ok to set it from Session on every request? Is there any other better approach?
if (HttpContext.Current.Session["User"] != null && HttpContext.Current.Session["User"] as Contracts.IUser != null)
{
HttpContext.Current.User = HttpContext.Current.Session["User"] as Contracts.IUser;
}
else
{
var service = new LoginService();
Contracts.ISer user = service.GetUser(filterContext.HttpContext.User.Identity.Name);
HttpContext.Current.Session["User"] = user;
HttpContext.Current.User = user;
}
}
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) {}
を}
私のログインコードは次のようである(AccountController.cs中) :
[Filters.AllowAnonymousActionFilter]
[HttpPost]
public JsonResult Login(string username, string password, bool rememberMe = false)
{
LoginService service = new LoginService();
Contracts.IUser user = service .Login(username, password);
System.Web.HttpContext.Current.Session["User"] = value;
System.Web.HttpContext.Current.User = value;
// set cookie i.e. ASPX_AUTH, if remember me, make cookie persistent, even if user closed browser
if (System.Web.Security.FormsAuthentication.IsEnabled)
System.Web.Security.FormsAuthentication.SetAuthCookie(username, rememberMe);
return new SuccessResponseMessage().AsJsonNetResult();
}
Contracts.IUserインタフェース:
public interface IUser : IPrincipal
{
Contracts.IUserInfo UserInfo { get; }
Contracts.ICultureInfo UserCulture { get; }
}
私の質問はこれです:
System.Web.HttpContext.Current.User
は、すべての要求にresetedされます。要求ごとにセッション値をHttpContext.Current.User
に設定してもよろしいですか?他のより良いアプローチはありますか?ベストプラクティスとは何ですか?また、マイクロソフトでは、この問題に対処するための複数の方法があるようだ(stackoverflow Custom Authorization in Asp.net WebApi - what a mess?もこれに関する多くの記事をgoogled)。これについて多くの混乱がありますが、asp.netコアで新しいAuthorizationを開発しました。
だから、これは全体のクッキーがあることを意味し、 (クライアント側は 'session id'だけを送信し、サーバはそれと一致しますが、クライアント側はすべての情報を送信します)?私はどこかでクッキークライアントのサイズに4kの制限がありますが、それはもちろん大変です。あなたは通常、ユーザー名、ID、文化、IPのような情報が必要です... – broadband