Я хочу сделать пользовательскую проверку подлинности, потому что у нас много контроллеров, и имеет смысл создавать глобальный фильтр, который применяется для всех контроллеров и их действий, за исключением страницы входа.Пользовательские ASP.NET MVC Forms Authentication
В Global.asax.cs я добавил следующий глобальный фильтр:
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
:
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
будет сброшена на каждом запросе. Можно ли установить HttpContext.Current.User
со значением Session для каждого запроса? Есть ли другой лучший подход? Что такое лучшая практика? Кроме того, Microsoft, похоже, имеет несколько способов решения этой проблемы (googled много статей об этом, также в stackoverflow Custom Authorization in Asp.net WebApi - what a mess?). В этом есть много путаницы, хотя они разработали новую авторизацию в ядре asp.net.
Таким образом, это означает, что все куки сохраненный на стороне клиента (клиентская сторона не отправляет только «идентификатор сеанса», который затем совпадает с сервером, но клиентская сторона отправляет всю информацию)? Я где-то читал, что для размера файла cookie существует ограничение 4 тыс., Но это, конечно, много. Вам обычно нужна только информация, как имя пользователя, идентификатор, культура, IP, ... – broadband