• .NET Framework Membership.ValidateUser(string username, string password) 深度剖析,以及动态配置实现


    Membership 是System.Web.Security 用户登录验证的一个封装类静态类,提供 Membership.ValidateUser(string username, string password)  返回一个bool类型的等方法。

    由于.NET之前不开源很多时候只知道大概的实现原理,比如调用这个类方法前需要在项目实现一个继承 MembershipProvider的类,该类提供了   public abstract bool ValidateUser(string username, string password);等抽象方法。

    大概思路就是 Membership 封装 MembershipProvider派生类的初始化等操作来调用该类的具体实现。

    先看看 Membership 类的几个关键代码 

       public static class Membership
        {
            public static MembershipProviderCollection Providers { get { Initialize(); return s_Providers; } }
    
            public static MembershipProvider Provider
            {
                get
                {
                    Initialize();
                    if (s_Provider == null)
                    {
                        throw new InvalidOperationException(SR.GetString(SR.Def_membership_provider_not_found));
                    }
                    return s_Provider;
                }
            }
    
            private static void Initialize()
            {
                if (s_Initialized && s_InitializedDefaultProvider)
                {
                    return;
                }
                if (s_InitializeException != null)
                    throw s_InitializeException;
    
                if (HostingEnvironment.IsHosted)
                    HttpRuntime.CheckAspNetHostingPermission(AspNetHostingPermissionLevel.Low, SR.Feature_not_supported_at_this_level);
    
                lock (s_lock)
                {
                    if (s_Initialized && s_InitializedDefaultProvider)
                    {
                        return;
                    }
                    if (s_InitializeException != null)
                        throw s_InitializeException;
    
                    bool initializeGeneralSettings = !s_Initialized;
                    // the default provider can be initialized once the pre start init has happened (i.e. when compilation has begun)
                    // or if this is not even a hosted scenario
                    bool initializeDefaultProvider = !s_InitializedDefaultProvider &&
                        (!HostingEnvironment.IsHosted || BuildManager.PreStartInitStage == PreStartInitStage.AfterPreStartInit);
    
                    if (!initializeDefaultProvider && !initializeGeneralSettings)
                    {
                        return;
                    }
    
                    bool generalSettingsInitialized;
                    bool defaultProviderInitialized = false;
                    try
                    {
                        //通过web.config 配置实现初始化的配置参数。
                        RuntimeConfig appConfig = RuntimeConfig.GetAppConfig();
                        MembershipSection settings = appConfig.Membership;
                        generalSettingsInitialized = InitializeSettings(initializeGeneralSettings, appConfig, settings);
                        defaultProviderInitialized = InitializeDefaultProvider(initializeDefaultProvider, settings);
                        // VSO #265267 log warning in event log when using clear password and encrypted password in Membership provider
                        // VSO #433626 In order to minimize the behavior change, we are going to read the password format from the config settings only instead of getting from the provider class
                        // Also allow user to opt-out this feature.
                        if (AppSettings.LogMembershipPasswordFormatWarning)
                        {
                            CheckedPasswordFormat(settings);
                        }
                    }
                    catch (Exception e)
                    {
                        s_InitializeException = e;
                        throw;
                    }
    
                    // update this state only after the whole method completes to preserve the behavior where
                    // the system is uninitialized if any exceptions were thrown.
                    if (generalSettingsInitialized)
                    {
                        s_Initialized = true;
                    }
                    if (defaultProviderInitialized)
                    {
                        s_InitializedDefaultProvider = true;
                    }
                }
            }
    
            private static bool InitializeSettings(bool initializeGeneralSettings, RuntimeConfig appConfig, MembershipSection settings)
            {
                if (!initializeGeneralSettings)
                {
                    return false;
                }
    
                s_HashAlgorithmType = settings.HashAlgorithmType;
                s_HashAlgorithmFromConfig = !string.IsNullOrEmpty(s_HashAlgorithmType);
                if (!s_HashAlgorithmFromConfig)
                {
                    // If no hash algorithm is specified, use the same as the "validation" in "<machineKey>".
                    // If the validation is "3DES", switch it to use "SHA1" instead.
                    MachineKeyValidation v = appConfig.MachineKey.Validation;
                    if (v != MachineKeyValidation.AES && v != MachineKeyValidation.TripleDES)
                        s_HashAlgorithmType = appConfig.MachineKey.ValidationAlgorithm;
                    else
                        s_HashAlgorithmType = "SHA1";
                }
                s_Providers = new MembershipProviderCollection();
                if (HostingEnvironment.IsHosted)
                {
                    ProvidersHelper.InstantiateProviders(settings.Providers, s_Providers, typeof(MembershipProvider));
                }
                else
                {
                    foreach (ProviderSettings ps in settings.Providers)
                    {
                        Type t = Type.GetType(ps.Type, true, true);
                        if (!typeof(MembershipProvider).IsAssignableFrom(t))
                            throw new ArgumentException(SR.GetString(SR.Provider_must_implement_type, typeof(MembershipProvider).ToString()));
                        MembershipProvider provider = (MembershipProvider)Activator.CreateInstance(t);
                        NameValueCollection pars = ps.Parameters;
                        NameValueCollection cloneParams = new NameValueCollection(pars.Count, StringComparer.Ordinal);
                        foreach (string key in pars)
                            cloneParams[key] = pars[key];
                        provider.Initialize(ps.Name, cloneParams);
                        s_Providers.Add(provider);
                    }
                }
    
                TimeSpan timeWindow = settings.UserIsOnlineTimeWindow;
                s_UserIsOnlineTimeWindow = (int)timeWindow.TotalMinutes;
    
                return true;
            }
            private static bool InitializeDefaultProvider(bool initializeDefaultProvider, MembershipSection settings)
            {
                if (!initializeDefaultProvider)
                {
                    return false;
                }
                s_Providers.SetReadOnly();
                if (settings.DefaultProvider == null || s_Providers.Count < 1)
                    throw new ProviderException(SR.GetString(SR.Def_membership_provider_not_specified));
                s_Provider = s_Providers[settings.DefaultProvider];
                if (s_Provider == null)
                {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Def_membership_provider_not_found), settings.ElementInformation.Properties["defaultProvider"].Source, settings.ElementInformation.Properties["defaultProvider"].LineNumber);
                }
                return true;
            }
        }
    
    //用户实现的派生类    
    public class SQLMembershipProvider: MembershipProvider
        {
            public SQLMembershipProvider()
            {
               
            }
    
            public override bool ValidateUser(string username, string password)
            {
                 //验证用户密码的具体用户级逻辑
            }
        }  

    webconfig 配置派生类参数

    <membership defaultProvider="TestMembershipProvider">
          <providers>
            <clear />
            <add connectionStringName="TestADConnectionString" connectionUsername="" connectionPassword="" attributeMapUsername="sAMAccountName" name="SQLMembershipProvider" type="Summer.Net.Security.SQLMembershipProvider,Summer.Net.Security" />
          </providers>
        </membership>
    

      

  • 相关阅读:
    UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
    蓝桥杯 修改数组 (巧用并查集)
    luoguP3242 [HNOI2015]接水果
    CF757F Team Rocket Rises Again
    luoguP2597 [ZJOI2012]灾难
    luoguP4103 [HEOI2014]大工程
    luoguP3233 [HNOI2014]世界树
    luoguP2495 [SDOI2011]消耗战
    CF613D Kingdom and its Cities
    51nod 1584 加权约数和
  • 原文地址:https://www.cnblogs.com/ms_senda/p/12499096.html
Copyright © 2020-2023  润新知