WebForms中的方法属性

时间:2014-05-22 22:09:03

标签: c# asp.net webforms

将安全逻辑分配给ASP.NET WebForms中的方法的最佳方法是什么?如果用户登录,而不是在每种方法下检查,我们不能使用方法属性吗? 例如,而不是这样做:

protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        if (!UserLoggedIn)
        {
            Response.Redirect("/login");
        }
        //Do stuff
    }

我想做类似下面的事情。我已经看到它在ASP.NET MVC应用程序中完成,但我想知道我是否可以通过webforms实现它。还有什么是确保只有经过身份验证的用户可以继续而其他人被重定向到登录页面的最佳做法?

Ex:期望。其中Secure是方法属性:

[Secure]
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        //Do stuff
    }

如何创建此类方法属性?如果那是不可能的,你会怎么建议我这样做?我在page_load或oninit上有很多需要这个的用户控件,我正在寻找一种更好的方法来实现它。

3 个答案:

答案 0 :(得分:5)

声明您的属性

[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。

答案 1 :(得分:1)

一个可能的解决方案是一个PageBase助手类,以避免检查ASP.NET Web上每个页面上的条件,并且只是继承了aspx.cs类中的页面。类似下面的代码:

例如,您希望确保某些Web表单只能由管理员用户访问,然后您可以使用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()是枚举,但如果您愿意,也可以使用普通字符串

并且在您的Web表单类中,您只继承此基类:

e.g。 AdminPage1.aspx.cs

public partial class AdminPage1: AdminPageBase
{
    //....
}

e.g。 AdminPage2.aspx.cs

public partial class AdminPage2: AdminPageBase
{
    //....
}
     

并且您可以始终对解决方案中的所有其他页面执行相同操作。   你也可以在你的PageBase课程上将Page_Init更改为Page_Load,但我选择Page_Init的原因是因为你可能需要Page_Load事件来检查你网页上的其他内容,这样才能检查你网站的安全性。

答案 2 :(得分:1)

为了拦截方法调用,我建议使用一些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会发出MSIL指令,PostSharp会受到轻微的性能影响,或者根本不会导致性能下降。