自定义授权IActionResults在aspnet-5 mvc-6中

时间:2015-12-19 20:30:05

标签: c# asp.net-core authorization asp.net-core-mvc actionresult

在ASP.NET 4 MVC5中,我有这个类允许我返回针对JSON端点的未经身份验证的响应的自定义响应。在这里。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (IsAjax(filterContext))
        {
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    success = false,
                    error = "You must be signed in."
                }
            };
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }

    private bool IsAjax(AuthorizationContext filterContext)
    {
        return filterContext.ActionDescriptor.GetFilterAttributes(true).OfType<AjaxAttribute>().FirstOrDefault() !=
                null;
    }
}

但是,在MVC6中,新的AuthorizeAttribute无法覆盖创建自定义IActionResult结果。我如何在MVC6中执行此操作?

1 个答案:

答案 0 :(得分:0)

在查看来源后我终于明白了。

public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
    Func<CookieRedirectContext, Task> _old;
    public CustomCookieAuthenticationEvents()
    {
        _old = OnRedirectToLogin;
        OnRedirectToLogin = OnCustomRedirectToLogin;
    }

    public Task OnCustomRedirectToLogin(CookieRedirectContext context)
    {
        var actionContext = context.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
        if (actionContext.ActionContext == null)
            return _old(context);

        if (actionContext.ActionContext.ActionDescriptor.FilterDescriptors.Any(x => x.Filter is AjaxAttribute))
        {
            // this is an ajax request, return custom JSON telling user that they must be authenticated.
            var serializerSettings = context
                .HttpContext
                .RequestServices
                .GetRequiredService<IOptions<MvcJsonOptions>>()
                .Value
                .SerializerSettings;

            context.Response.ContentType = "application/json";

            using (var writer = new HttpResponseStreamWriter(context.Response.Body, Encoding.UTF8))
            {
                using (var jsonWriter = new JsonTextWriter(writer))
                {
                    jsonWriter.CloseOutput = false;
                    var jsonSerializer = JsonSerializer.Create(serializerSettings);
                    jsonSerializer.Serialize(jsonWriter, new
                    {
                        success = false,
                        error = "You must be signed in."
                    });
                }
            }

            return Task.FromResult(0);
        }
        else
        {
            // this is a normal request to an endpoint that is secured.
            // do what ASP.NET used to do.
            return _old(context);
        }
    }
}

然后,按如下方式使用此事件类:

services.Configure<IdentityOptions>(options =>
{
    options.Cookies.ApplicationCookie.Events = new CustomCookieAuthenticationEvents();
});

ASP.NET 5确实让简单的事情变得更难。尽管如此,我现在可以更精细地定制事物,而不会影响其他部分。此外,源代码非常容易阅读/理解。我很高兴有信心我遇到的任何问题很容易被识别为错误或通过查看来源解决。

为未来干杯!