• ASP.NET 2.0 成员资格和角色管理授权


    从严格意义上来说,ASP.NET 2.0 的成员资格、角色管理授权和 .NET 角色安全性没有多大关系。只不过,Microsoft 替我们完成了一些原本需要我们自己进行的工作而已。

    在这两种新的技术中使用的"提供程序模型"倒是值得我们好好学习一下,因为这个 IoC 概念非常相似。


    成员资格

    成员资格提供了通用的用户管理功能,诸如注册、登录、找回密码等,加上与之配套的可视化控件,我们“几乎”不用在编写额外的代码就可以工作。实际上真是如此吗?MemebershipUser 属性太少,显然不大适合我们的商业应用;注册和登录控件有缺乏验证码,缺乏安全性;…… 当然我们还可以使用自定义验证和提供程序,不过如此一来还不如自己参考"提供者模型"开发一套呢,毕竟独立的 Passport 才是我们所需要的,更不要说和既有系统进行整合了,总之 ASP.NET 提供的这个新功能,食之无味,弃之可惜。有关成员资格和角色管理的使用不是本文的重点,详情可参考 MSDN 文档。

    成员资格由 Membership、MembershipUser、MembershipProvider 组成,Membership 是个静态类,为用户提供了大量用户相关的操作方法,MembershipUser 则是用户实体类,除了用户属性外也有一些用户自身的操作方法,而 MembershipProvider 自然就是提供程序的基础抽象类了,它规范了提供程序的接口。

     单击在新窗口中浏览图片

    我们分析一下 Membership 代码(局部代码),看看如何获取真实的目标提供程序对象的。其实过程也很简单,读取配置获取类型信息,然后用反射创建目标提供程序对象实例。

    System.System.Web.Security.Membership

    复制C#源代码
    // 我们从 ValidateUser 方法入手。
    public static bool ValidateUser(string username, string password)
    {
        // 通过 Provider 属性获取提供程序对象
        return Membership.Provider.ValidateUser(username, password);
    }
    public static MembershipProvider Provider
    {
    get
    {
            // 应该是通过 Initialize() 方法获取,并赋值给 s_Provider 变量的。
            Membership.Initialize();
    return Membership.s_Provider;
    }
    }
    private static void Initialize()
    {
        // 从配置文件中读取配置信息
        RuntimeConfig config1 = RuntimeConfig.GetAppConfig();
    MembershipSection section1 = config1.Membership;
    Membership.s_Providers = new MembershipProviderCollection();
        // 使用 ProvidersHelper.InstantiateProviders 方法从配置信息中读取设置。
        ProvidersHelper.InstantiateProviders(section1.Providers, Membership.s_Providers, typeof(MembershipProvider));
        // 将缺省提供程序对象赋值给 s_Provider 变量。
        Membership.s_Provider = Membership.s_Providers[section1.DefaultProvider];
    Membership.s_Initialized = true;
    }
    public static void ProvidersHelper.InstantiateProviders(ProviderSettingsCollection configProviders, ProviderCollection providers, Type providerType)
    {
        // 循环读取配置信息,并创建提供程序对象。
        foreach (ProviderSettings settings1 in configProviders)
    {
    providers.Add(ProvidersHelper.InstantiateProvider(settings1, providerType));
    }
    }
    public static ProviderBase ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type providerType)
    {
    ProviderBase base1 = null;
    try
    {
            // 调用 HttpRuntime.CreatePublicInstance 创建提供程序对象。
            base1 = (ProviderBase) HttpRuntime.CreatePublicInstance(type1);
    }
    catch (Exception exception1)
    {
    }
    return base1;
    }
    internal static object HttpRuntime.CreatePublicInstance(Type type)
    {
        // 利用反射创建对象
        return Activator.CreateInstance(type);
    }

    下面我们分析一下 Login 控件的源码,我们会发现其内部不过是自动调用 Membership 和 MembershipProvider 进行操作而已。

    System.Web.UI.WebControls.Login

    复制C#源代码
    private void AttemptLogin()
    {
    if ((this.Page == null) || this.Page.IsValid)
    {
    LoginCancelEventArgs args1 = new LoginCancelEventArgs();
    this.OnLoggingIn(args1);
    if (!args1.Cancel)
    {
    AuthenticateEventArgs args2 = new AuthenticateEventArgs();
                // 调用核心代码
                this.OnAuthenticate(args2);
                // 看到了什么?标准的身份验证代码。详情可以查看上一篇Blog。
                if (args2.Authenticated)
    {
    FormsAuthentication.SetAuthCookie(this.UserNameInternal, this.RememberMeSet);
    this.OnLoggedIn(EventArgs.Empty);
    this.Page.Response.Redirect(this.GetRedirectUrl(), false);
    }
    else
    {
    this.OnLoginError(EventArgs.Empty);
    if (this.FailureAction == LoginFailureAction.RedirectToLoginPage)
    {
    FormsAuthentication.RedirectToLoginPage("loginfailure=1");
    }
    ITextControl control1 = (ITextControl) this.TemplateContainer.FailureTextLabel;
    if (control1 != null)
    {
    control1.Text = this.FailureText;
    }
    }
    }
    }
    }
    protected virtual void OnAuthenticate(AuthenticateEventArgs e)
    {
    AuthenticateEventHandler handler1 = (AuthenticateEventHandler) base.Events[Login.EventAuthenticate];
    if (handler1 != null)
    {
            // 用户使用了自定义身份验证服务
            handler1(this, e);
    }
    else
    {
            // 使用成员资格提供程序
            this.AuthenticateUsingMembershipProvider(e);
    }
    }
    private void AuthenticateUsingMembershipProvider(AuthenticateEventArgs e)
    {
        // 使用 LoginUtil.GetProvider 获取成员资格提供程序对象,并调用其 ValidateUser 进行身份验证。
        e.Authenticated = LoginUtil.GetProvider(this.MembershipProvider).ValidateUser(this.UserNameInternal, this.PasswordInternal);
    }
    internal static LoginUtil.MembershipProvider GetProvider(string providerName)
    {
    if (string.IsNullOrEmpty(providerName))
    {
    return Membership.Provider;
    }
        // 调用 Membership 相关属性,获取提供程序对象。
        MembershipProvider provider1 = Membership.Providers[providerName];
    if (provider1 == null)
    {
    throw new HttpException(SR.GetString("WebControl_CantFindProvider"));
    }
    return provider1;
    }


    角色管理授权

    在实际开发中,除了用户(User)和角色(Role)以外,我们还需要权限(Permission)这个概念。角色更像是用户组(Users Group),用户可以加入一个或多个用户组,每个用户组又拥有多个权限。有了权限,我们就可以动态赋予用户组不同的权力,比如我们可以临时授予 A 组执行 XX 的权力,三天后我们再取消该权力,显然没有权限的设计会缺乏灵活性。

    ASP.NET 2.0 的角色管理授权,由 RoleManagerModule、Roles、RoleProvider、RolePrincipa 共同组成。系统会自动载入 RoleManagerModule 这个 HttpModule,Roles 为用户提供角色相关的操作方法,而 RoleProvider 自然是提供程序的抽象类了。至于 RolePrincipa 干什么用,看看下面的代码自然就明白了。

    System.Web.Security.RoleManagerModule

    复制C#源代码
    private void OnEnter(object source, EventArgs eventArgs)
    {
        // ...
        // 注意下面的代码, RoleManagerModule 使用 RolePrincipal 替代了缺省的 GenericPrincipal。
        if (!(context1.User is RolePrincipal))
    {
    context1.User = new RolePrincipal(context1.User.Identity);
    }
    }

    转载地址:http://www.chenjiliang.com/Article/View.aspx?ArticleID=1428&TypeID=84

  • 相关阅读:
    Enumerable.Distinct方法去重
    datatable使用lambda
    jQuery获取单选框(复选框)选中的状态
    从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
    SQL Server 中WITH (NOLOCK)浅析
    C#将int型数字转换成3位字符串,不足的时候,前面补0
    window.locatin.href 中特殊字符串问题
    windows下git bash不显示中文问题解决
    python获取文件行数
    自定义异常以及触发异常
  • 原文地址:https://www.cnblogs.com/yiki/p/611028.html
Copyright © 2020-2023  润新知