禁止直接访问剃刀页面处理程序

时间:2019-04-26 10:31:43

标签: c# asp.net-core razor-pages asp.net-core-2.2

我已经创建了剃须刀页面以注销用户。经过身份验证的用户访问路线/account/logout时,我想向他显示带有成功消息的页面,如果用户是匿名用户,则该页面不会被授权。但是,不能通过直接URL输入访问此成功页面。

下面的代码可以很好地工作,除非任何人都可以导航到充当普通页面的/account/logout/success(并且由于不是负责退出的人,因此可能会造成混淆)。

public class LogoutModel : CustomPageModel
{
    private readonly SignInManager _signInManager;

    public LogoutModel(SignInManager signInManager) => _signInManager = signInManager;

    public async Task<IActionResult> OnGetAsync()
    {
        if (_signInManager.IsSignedIn(User))
        {
            await _signInManager.SignOutAsync();
            return RedirectToPage("Logout", "Success");
        }

        return Unauthorized();
    }

    public void OnGetSuccess()
    {
    }
}

如何防止处理程序OnGetSuccess可以直接访问?

3 个答案:

答案 0 :(得分:0)

选择this question,以了解可能的方法。

不知道我是否建议您选择那条路线,因为它有点脏而且不必要地复杂。您可以为已登录/注销的用户返回不同的状态消息。

Logout.cshtml.cs

public class LogoutModel : CustomPageModel
{
    private readonly SignInManager _signInManager;

    public LogoutModel(SignInManager signInManager) => _signInManager = signInManager;

    public string StatusMessage { get; set; }

    public async Task<IActionResult> OnGetAsync()
    {
        if (_signInManager.IsSignedIn(User))
        {
            await _signInManager.SignOutAsync();
            StatusMessage = "Successfully logged out!";
            return Page();
        }
        else {
            StatusMessage = "Already logged out!";
            return Page();
        }

    }
}

Logout.cshtml

@page
@model X.LogoutModel

@Model.StatusMessage

答案 1 :(得分:0)

我已经通过使用Attribute和IPageFilter(检查Referer标头)解决了这个问题。

首先,我创建了属性

[AttributeUsage(AttributeTargets.Method)]
public class ChildHandlerAttribute : Attribute
{
}

然后我用它装饰了GetOnSuccess()处理程序

[ChildHandler]
public void OnGetSuccess()
{
}

然后,我实现了检查子处理程序的Referer标头的过滤器。

public class ChildHandlerAsyncPageFilter : IAsyncPageFilter
{
    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
    {
        var pageHandlerExecutedContext = await next();

        if (pageHandlerExecutedContext.HandlerMethod?.MethodInfo.GetCustomAttribute<ChildHandlerAttribute>() == null)
        {
            return;
        }

        var referrer = context.HttpContext.Request.Headers["Referer"].ToString();
        var request = pageHandlerExecutedContext.HttpContext.Request;

        if (!referrer.StartsWith($"{request.Scheme}://{request.Host}"))
        {
            pageHandlerExecutedContext.Result = new NotFoundResult();
        }
    }

    public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => Task.CompletedTask;
}

最近我已将过滤器添加到 Startup.cs

中的管道中
services.AddMvc(options =>
{
    options.Filters.Add<ChildHandlerAsyncPageFilter>();
});

答案 2 :(得分:0)

在您的情况下,用户出局并以匿名用户身份重定向。因此,不能说这里只有某些用户可以访问此操作。

您应该以其他方式解决此问题。例如,您可以在LogOut操作中设置Cookie中的值,然后在Success操作中签入。为了获得更高的安全性,请应用MVC用于CSRF的模式。