Сессия становится пустой в MVC AuthorizeAttribute
Я использую атрибут AuthorizeAttribute, чтобы проверить, что у пользователей установлен cookie-файл старше 18 лет для доступа к страницам.
Это прекрасно работает, но я немного расширяюсь. Поскольку все представления используют этот атрибут, я использую его, чтобы я мог запустить свой сайт раньше. Если для любого URL используется add? VIEWSITE = true, он установит переменную Session и предоставит им доступ к сайту. В противном случае они направляются на удерживающую страницу.
Это отлично работает при первом запуске страницы. Но я использую кэширование вывода на странице, и при следующей загрузке страницы мой httpcontext.session будет нулевым?
Я добавил переменную "Order" в мои атрибуты, чтобы они выполнялись в правильном порядке:
[OfAge(Order = 1)]
[OutputCache(Order = 2, Duration = 2000, VaryByParam = "categoryName")]
Снипит из моего атрибута:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
HttpRequestBase req = httpContext.Request;
HttpResponseBase res = httpContext.Response;
DateTime Live_Date = new DateTime(2011, 07, 01, 07, 0, 0);
if (DateTime.Now > Live_Date || req.QueryString["VIEWSITE"] != null || httpContext.Session["VIEWSITE"] != null)
{
httpContext.Session["VIEWSITE"] = true;
Есть ли что-то, чего мне здесь не хватает, чтобы я мог читать / устанавливать переменные сеанса после загрузки страницы из кэша?
Чтобы было ясно, это httpContext.Session, который является нулевым, а не определенно httpContext.Session["VIEWSITE"]
1 ответ
Спустя 3 года я столкнулся с подобной проблемой. Сейчас я не эксперт, но я считаю, что каждый контекстный вызов контроллера уникален в своем собственном пространстве, поэтому httpContext.Session будет нулевым при новом вызове.
Моя проблема возникла в форме зарегистрированного пользователя AD, который я хотел сохранить (с его пользовательскими разрешениями приложения) в переменной сеанса. Я также расширяю атрибут AuthorizationAttribute, но когда этот фильтр применяется к действию контроллера, httpContext имеет значение null, даже если пользователь был сохранен.
Для людей, борющихся с той же проблемой, можно обойти это путем создания базового контроллера, где этот пользователь и его состояние сеанса сохраняются во всех других контроллерах (наследуя базовый контроллер).
ех.
Моя модель:
public class LoggedInUser
{
public somenamespace.userclass UserProfile { get; set; }
public List<somenamespace.user_permission_class> UserPermissions { get; set; }
}
Мой базовый контроллер:
public class ControllerBase : Controller
{
private LoggedInUser _LoginUser;
public LoggedInUser LoginUser
{
get
{
if (_LoginUser != null)
return _LoginUser;
if (Session["_LoginUser"] == null)
return null;
return Session["_LoginUser"] as LoggedInUser;
}
set
{
_LoginUser = value;
Session["_LoginUser"] = _LoginUser;
}
}
public void PerformUserSetup(string sUsername) // sUsername for testing another user, otherwise User.Identity will be used.
{
sUsername = string.IsNullOrEmpty(sUsername) ? User.Identity.Name : sUsername;
sUsername = (sUsername.IndexOf("\\") > 0) ? sUsername.Split('\\').ToArray()[1] : sUsername;
// Todo - SQL conversion to stored procedure
List<userclass> tmpUser = Root.Query<userclass>(/*sql to select user*/).ToList();
List<user_permission_class> tmpUserpermissions = Root.Query<user_permission_class>(/*sql to select user permissions*/).ToList();
LoggedInUser _LoginUser = new LoggedInUser();
_LoginUser.UserProfile = tmpUser.First();
_LoginUser.UserPermissions = tmpUserpermissions;
LoginUser = _LoginUser;
}
}
Мой HomeController (стандартный для любого примера MVC):
public class HomeController : ControllerBase
{
[Authorize] // Standard AuthorizeAttribute (AD test)
public ActionResult Index()
{
if (Session["_LoginUser"] == null)
PerformUserSetup("");
return View();
}
}
Мой пользовательский фильтр проверки прав доступа, который я буду использовать для любого другого действия контроллера:
public class PermissionAuthorize : AuthorizeAttribute
{
private readonly string[] permissions;
public PermissionAuthorize(params string[] perms)
{
this.permissions = perms;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool auth = false;
if (httpContext.Session["_LoginUser"] == null)
{
// Do nothing as auth is false.
}
else
{
// Check permissions and set auth = true if permission is valid.
auth = true;
}
return auth;
}
/* not using
public override void OnAuthorization(AuthorizationContext filterContext)
{
var tmp = filterContext.HttpContext.Session;
}
*/
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Todo - direct to "unauth page"
base.HandleUnauthorizedRequest(filterContext);
}
}
Использование:
public class Some_OtherController : /*PossibleNamespace?.*/ControllerBase
{
[PermissionAuthorize("somepermission")] // This was a CRUD application thus 1 permission per actionresult
public ActionResult ViewWhatever()
{
....
}
}