san*_*084 3 authentication asp.net-mvc session redirect kendo-ui
我有一个 ASP MVC 页面,当会话过期时需要重定向到登录页面。如果用户位于页面中且会话过期,并且用户刷新页面,则用户将被重定向到登录页面。但是,如果用户单击按钮,页面永远不会重定向到登录页面。我在每个控制器操作方法中都有一个自定义 ActionFilter 来检查会话,并且我使用“RedirectToRouteResult”对象来重定向页面,但是它似乎仅在用户刷新页面时才起作用,而不是在单击按钮时起作用。
这是我的自定义操作过滤器:
public class CustomCheckSessionOutAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string actionName = filterContext.ActionDescriptor.ActionName.ToLower().Trim();
//Check Start with
if (!actionName.StartsWith("Login") && !actionName.StartsWith("LogOff"))
{
var session = HttpContext.Current.Session["LoggedInUserInfo"];
//Redirects user to login screen if session has timed out
if (session == null)
{
base.OnActionExecuting(filterContext);
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Account",
action = "Login",
returnUrl = ((HttpRequestWrapper)((HttpContextWrapper)filterContext.HttpContext).Request).Url
}));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是控制器中操作方法的示例:
[Authorize(Roles = "Client")]
[CustomCheckSessionOut]
public ActionResult GetOrders([DataSourceRequest] DataSourceRequest request, string orderId)
{
}
Run Code Online (Sandbox Code Playgroud)
如果会话过期并且单击按钮,我有什么建议如何将用户重定向到登录页面?谢谢。
更新: 感谢 Fabien,我用他的方法解决了这个问题,如下所示:
全局.asax.cs
protected void Application_EndRequest()
{
var context = new HttpContextWrapper(Context);
// If we're an ajax request, and doing a 302, then we actually need to do a 401
if (Context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
{
Context.Response.Clear();
Context.Response.StatusCode = 401;
Context.Response.StatusDescription = "expiredSession";
}
}
Run Code Online (Sandbox Code Playgroud)
JavaScript:
$(document).ajaxComplete(function (e, xhr, options) {
if (xhr != null) {
if (xhr.getResponseHeader('X-Responded-JSON') != null) {
var responseHeader = jQuery.parseJSON(xhr.getResponseHeader('X-Responded-JSON'));
if (responseHeader.status === 401) {
e.stopPropagation();
window.location.href = responseHeader.headers.location;
}
}
if (xhr.status === 401 && xhr.statusText === "expiredSession") {
// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event
e.stopPropagation();
location.reload();
}
}
});
Run Code Online (Sandbox Code Playgroud)
看来您的控制器操作是由 Kendo 组件使用 AJAX 调用的。您无法从 AJAX 调用重定向页面。您可以返回 HttpUnauthorizedResult,而不是返回 RedirectToRouteResult,在客户端使用 javascript 调用捕获它,如果状态代码为 401 - 未经授权,则触发页面重定向到您的登录操作。
您可以像这样更新自定义操作过滤器来处理这两种情况:
public class CustomCheckSessionOutAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string actionName = filterContext.ActionDescriptor.ActionName.ToLower().Trim();
//Check Start with
if (!actionName.StartsWith("login") && !actionName.StartsWith("logoff"))
{
var session = filterContext.HttpContext.Session["LoggedInUserInfo"];
//Redirects user to login screen if session has timed out
if (session == null)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
// Indicate to the remote caller that the session has expired and where to redirect
filterContext.HttpContext.Response.Headers.Add("Location", new UrlHelper(filterContext.RequestContext).Action("Login", "Account"));
filterContext.Result = new HttpUnauthorizedResult("Session expired");
}
else
{
//Redirects user to login screen if session has timed out and request is non AJAX
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Account",
action = "Login",
returnUrl = filterContext.HttpContext.Request.Url
}));
}
}
}
base.OnActionExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
Kendo grid 使用 DataSource 组件从远程源读取数据,它有一个名为“Error”的事件,您可以使用该事件来捕获 401 - 会话过期错误。
@(Html.Kendo()
.Grid<YourModel>()
.Name("GridPOSearch")
.DataSource(d => d.Ajax()
.Read("GetOrders", "YourController")
.Events(e => e.Error("error"))))
Run Code Online (Sandbox Code Playgroud)
function error(e) {
if (e.errorThrown === "Session expired") {
location.href = e.xhr.getResponseHeader("Location");
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想在小部件初始化后绑定到错误事件,你可以这样做:
function datasource_error(e) {
if (e.errorThrown === "Session expired") {
location.href = e.xhr.getResponseHeader("Location");
}
}
$("#GridPOSearch").data("kendoGrid").dataSource.bind("error", datasource_error);
Run Code Online (Sandbox Code Playgroud)
您可以替换“会话已过期”错误消息以更好地满足您的需要,只是不要忘记替换 JavaScript 代码中的检查,已在文档中显示。
您可以使用 jQuery 1.0 及更高版本在应用程序范围内执行此操作,将此代码片段添加到每个页面上加载的 javascript 文件中(在您的 _Layout.cshtml 中):
(function () {
$(document).ajaxComplete(function (e, xhr, options) {
if (xhr.status === 401 && xhr.statusText === "Session expired") {
// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event
e.stopPropagation();
location.href = xhr.getResponseHeader("Location");
}
});
})();
Run Code Online (Sandbox Code Playgroud)
我更新了动作过滤器和 kendo javascript 代码,以更优雅的方式设置重定向位置。
| 归档时间: |
|
| 查看次数: |
2007 次 |
| 最近记录: |