Каков наилучший способ назначения логики безопасности методу в ASP.NET WebForms? Где вместо проверки по каждому методу, если пользователь вошел в систему, мы не можем использовать атрибуты метода? Пример, вместо этого:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!UserLoggedIn)
{
Response.Redirect("/login");
}
//Do stuff
}
Я хотел бы сделать что-то вроде ниже. Я видел это в приложениях ASP.NET MVC, но мне интересно, могу ли я это сделать с помощью webforms. А также, что было бы лучшей практикой для обеспечения того, чтобы только аутентифицированный пользователь мог продолжить, а другие перенаправляются на страницу входа?
Пример: Желание. Где Secure - атрибут метода:
[Secure]
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//Do stuff
}
Как мне создать такой атрибут метода? И если это невозможно, как бы вы порекомендовали мне это сделать? У меня есть много usercontrols, которые нуждаются в этом на page_load или oninit, и я ищу лучший способ сделать это.
Объявите свой атрибут
[AttributeUsage(AttributeTargets.Class)]
public class SecureAttribute: Attribute
{
}
Создание пользовательского базового класса для всех форм
public class PageBase: Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var secureAttr = Attribute.GetCustomAttribute(this.GetType(), typeof (SecureAttribute));
if (secureAttr != null)
{
bool UserLoggedIn = false; // get actual state from DB or Session
if (!UserLoggedIn)
{
Response.Redirect("/login");
}
}
}
}
Наследовать все свои формы с помощью PageBase
[Secure]
public partial class Profile: PageBase
{
}
Создайте аналогичную UserControlBase для пользовательских элементов управления.
Чтобы перехватить вызовы методов, я бы рекомендовал использовать некоторую структуру AOP, например PostSharp, которая позволяет легко вводить поведение до и после выполнения метода путем объявления пользовательского аспекта:
[Serializable]
public class SecureAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
bool UserLoggedIn = false; // get from DB
if (!UserLoggedIn)
{
HttpContext.Current.Response.Redirect("/login");
}
}
}
И применяя этот атрибут к любому методу
public partial class Profile : Page
{
[Secure]
protected void Page_Load(object sender, EventArgs e)
{
}
[Secure]
protected void Button1_Click(object sender, EventArgs e)
{
}
}
Насколько мне известно, PostSharp снижает незначительный рейтинг производительности или вообще не влияет на производительность, поскольку PostSharp испускает инструкции MSIL.
Одним из возможных решений будет вспомогательный класс PageBase, чтобы избежать проверки этого условия на каждой отдельной странице веб-форм ASP.NET и просто наследует базу страниц в ваших классах aspx.cs. что-то вроде кода ниже:
например, вы хотите убедиться, что некоторые веб-формы доступны только пользователям Admin, тогда у вас может быть класс AdminPageBase для проверки этого условия для всех ваших веб-страниц.
ваш базовый класс:
public class AdminPageBase : System.Web.UI.Page { protected void Page_Init(object sender, EventArgs e) { if (!Context.User.Identity.IsAuthenticated || !HttpContext.Current.User.IsInRole(Roles.Admin.ToString())) { this.RedirectToLogin(); } } protected void RedirectToLogin() { //... Response.Redirect("~/SignIn.aspx"); } }
Примечание. Roles.Admin.ToString() - это перечисление, но вы также можете использовать простую строку, если хотите.
и в ваших классах веб-форм вы наследуете этот базовый класс следующим образом:
например, AdminPage1.aspx.cs
public partial class AdminPage1: AdminPageBase { //.... }
например, AdminPage2.aspx.cs
public partial class AdminPage2: AdminPageBase { //.... }
и вы всегда можете сделать то же самое для всех других страниц вашего решения. вы также можете изменить Page_Init на Page_Load на свой класс PageBase, но причина, по которой я выбрал Page_Init, потому что вам может понадобиться событие Page_Load, чтобы проверить другие вещи на вашей странице, чтобы было неплохо проверить безопасность вашего сайта.