SimpleMembershipProvider 的 MySql 实现

认 证我一直用的是微软的 Membership 体系,看 MySql 也实现了对应的 Provider,在新建立了一个 MVC4 项目后,把 Provider 一改就直接启动,然后就出错了。异常是“To call this method, the “Membership.Provider”property must be an instance of “ExtendedMembershipProvider”.

其原因是微软引进了一个叫 SimpleMembershipProvider 的东西。这个东西确实在数据库端做了大量的简化,根本没用到任何存储过程,表的数量也减少了很多,并且提供了与其它网站进行登录的功能。在 缺省情况下,WebMatrix.WebData.WebSecurity 利用 PreApplicationStart这个技术,在程序启动时将全局变量 Membership 中的"AspNetSqlMembershipProvider"与 Roles 中的"AspNetSqlRoleProvider"这两个 Provider 分别替换为 SimpleMembershipProvider 与 SimpleRoleProvider,于是在什么也没有改变的表面下,传统的 Membeship 体系就被 SimpleMembership 给代替了。从这个替换的动作就可以发现,微软写的 SimpleMembership 根本就是为自家的 SqlServer 服务的,如果你用 IlSpy 去看 SimpleMembershipProvider 的代码的话,就会看到 SqlServer 的 T-Sql 语法直接写在了代码中,直接使用这个 SimpleMembership 去连接 MySql 的话,是会出错的。

而 如果你直接用 MySql 的 Provider 的话,在 WebSecurity 中又会检查这个 Provider 是不是继承至微软新加入的 ExtendedMembershipProvider,当然,第三方怎么会跟的上微软这么自私的举动,于是上面那个异常就出现了。

在 各种网站的问答栏中,有人推荐把这个放在 Web.config 的中,其实这个只是阻止了上面 WebSecurity 将系统的 maching.config 中配置的缺省 AspNetSql 系列的 Provider 用它的 Simple 系统的 Provider 来代替而已,如果你用的是自定义的 Membership,那么这个 enableSimpleMembership 的设置是无用的。所以解决方法要么是不要使用微软给你的那个套登录验证机制,要么自己写一个 Provider 来实现。

下面来说正经的吧。在 WebSecurity 中如果使用的是SimpleMembershipProvider 那么会自动调用建表语句在数据库中建立要使用的表结构。如果不是 SimpleMembershipProvider 的话,则没有这个动作,所以建表要自己手动完成,或者在自定义的 Provider 中找合适的地方实现。在此,我直接用手动建立了表结构。

Create Table UserProfile (UserId int not null primary key auto_increment, UserName varchar(256) not null);

Create Table webpages_Membership (UserId int not null primary key, CreateDate datetime NULL, ConfirmationToken varchar(128) NULL,
IsConfirmed bit NULL, LastPasswordFailureDate datetime NULL, PasswordFailuresSinceLastSuccess int NOT NULL,
Password varchar(128) NOT NULL, PasswordChangedDate datetime NULL, PasswordSalt varchar(128) NOT NULL,
PasswordVerificationToken varchar(128) NULL, PasswordVerificationTokenExpirationDate datetime NULL);

Create Table webpages_OAuthMembership (Provider varchar(30) not null, ProviderUserId varchar(100) not null, UserId int not null);

Alter Table webpages_OAuthMembership Add Primary Key (Provider, ProviderUserId);

Create Table webpages_OAuthToken (Token varchar(100) not null primary key, Secret varchar(100) not null);

Create Table webpages_Roles (RoleId int not null primary key auto_increment, RoleName varchar(256) not null);

Create Table webpages_UsersInRoles (UserId int not null, RoleId int not null);

Alter Table webpages_UsersInRoles Add Primary Key (UserId, RoleId);

在 SimpleMembershipProvider 中,微软写进了大量的 Sql 代码,个人不喜欢这么做,于是就使用 LinqToEF 来实现数据端的操作。映射 EF 这个事情,你们比我懂,我就不说了。下面直接贴 MembershipProvider 的代码吧。在代码中,我的映射的 EF 叫 MembersAuthorContext。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Transactions;
using System.Web;
using System.Web.Helpers;
using System.Web.Security;
using WebMatrix.WebData;

namespace TestSimpleMembership.Help
{
    public class MySqlSimpleMembershipProvider : ExtendedMembershipProvider
    {
        private static string DEFAULT_PROVIDER_NAME = "MySQLMembershipProvider";
        private static string DEFAULT_NAME = "MySqlExtendedMembershipProvider";
        private static string DEFAULT_PROVIDER_CONFIG_NAME = "provider";

        private MembershipProvider preProvider;
        private MemberAuthorContext dbContext;
        private System.Data.Entity.DbSetuserProfiles;
        private System.Data.Entity.DbSetoAuthMemberships;
        private System.Data.Entity.DbSetroles;
        private System.Data.Entity.DbSetusersInRoles;
        private System.Data.Entity.DbSetmemberships;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (config == null) throw new ArgumentNullException("config");
            if (string.IsNullOrEmpty(name)) name = DEFAULT_NAME;
            base.Initialize(name, config);

            var providerName = config[DEFAULT_PROVIDER_CONFIG_NAME];
            if (!string.IsNullOrEmpty(providerName))
                this.preProvider = Membership.Providers[providerName] ?? Membership.Providers[DEFAULT_PROVIDER_NAME];
            if (this.preProvider != null)
                this.preProvider.ValidatingPassword += delegate(object sender, ValidatePasswordEventArgs args)
                {
                    this.OnValidatingPassword(args);
                };

            this.dbContext = new MemberAuthorContext();
            this.userProfiles = this.dbContext.userprofile;
            this.oAuthMemberships = this.dbContext.webpages_oauthmembership;
            this.roles = this.dbContext.webpages_roles;
            this.usersInRoles = this.dbContext.webpages_usersinroles;
            this.memberships = this.dbContext.webpages_membership;
        }

        public override bool ConfirmAccount(string accountConfirmationToken)
        {
            var rsl = from m in memberships
                      where m.ConfirmationToken == accountConfirmationToken
                      select new { UserId = m.UserId, ConfirmationToken = m.ConfirmationToken };

            if (!rsl.Any()) return false;

            var user = (from m in memberships where m.UserId == rsl.First().UserId select m).FirstOrDefault();
            if (user == null) return false;

            user.IsConfirmed = true;
            dbContext.SaveChanges();
            return true;
        }

        public override bool ConfirmAccount(string userName, string accountConfirmationToken)
        {
            var rsl = from membership in memberships
                      join userProfile in userProfiles on membership.UserId equals userProfile.UserId
                      where membership.ConfirmationToken == accountConfirmationToken &&
                          userProfile.UserName == userName
                      select new { UserId = membership.UserId, ConfirmationToken = membership.ConfirmationToken };

            if (!rsl.Any()) return false;

            var user = (from membership in memberships where membership.UserId == rsl.First().UserId select membership).FirstOrDefault();
            if (user == null) return false;

            user.IsConfirmed = true;
            dbContext.SaveChanges();
            return true;
        }

        public override string CreateAccount(string userName, string password, bool requireConfirmationToken)
        {
            if (String.IsNullOrEmpty(password))
                throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
            string passwordHash = Crypto.HashPassword(password);
            if (passwordHash.Length > 128)
                throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);

            if (String.IsNullOrEmpty(userName))
                throw new MembershipCreateUserException(MembershipCreateStatus.InvalidUserName);

            var user = (from u in userProfiles where u.UserName == userName select u).FirstOrDefault();
            if (user == null)
                throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError);
            if ((from m in memberships where m.UserId == user.UserId select m).Any())
                throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName);

            var token = requireConfirmationToken ? GenerateToken() : null;

            memberships.Add(new webpages_membership()
            {
                UserId = user.UserId,
                Password = passwordHash,
                CreateDate = DateTime.UtcNow,
                IsConfirmed = !requireConfirmationToken,
                PasswordFailuresSinceLastSuccess = 0,
                PasswordSalt = string.Empty,
                ConfirmationToken = token,
                PasswordChangedDate = DateTime.UtcNow
            });
            try
            {
                dbContext.SaveChanges();
            }
            catch (Exception e)
            {
                throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError);
            }
            return token;
        }

        private string GenerateToken()
        {
            using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider())
            {
                var bytes = new byte[16];
                provider.GetBytes(bytes);
                return HttpServerUtility.UrlTokenEncode(bytes);
            }
        }

        public override string CreateUserAndAccount(string userName, string password, bool requireConfirmation, IDictionary values)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                if ((from u in userProfiles where u.UserName == userName select u).FirstOrDefault() != null)
                    throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName);

                userprofile user = new userprofile() { UserName = userName };
                userProfiles.Add(user);
                dbContext.SaveChanges();
                var rsl = CreateAccount(userName, password, requireConfirmation);
                ts.Complete();
                return rsl;
            }
        }

        public override bool DeleteAccount(string userName)
        {
            var user = (from u in userProfiles where u.UserName == userName select u).FirstOrDefault();
            if (user == null) return false;

            foreach (var membership in from m in memberships where m.UserId == user.UserId select m)
                memberships.Remove(membership);

            dbContext.SaveChanges();
            return true;
        }

        public override string GeneratePasswordResetToken(string userName, int tokenExpirationInMinutesFromNow)
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");

            var user = getConfirmedUser(userName);
            if (user == null)
                throw new InvalidOperationException();

            var membership = (from m in memberships
                              where m.UserId == user.UserId && m.PasswordVerificationTokenExpirationDate > DateTime.UtcNow
                              select m).FirstOrDefault();

            if (membership.PasswordVerificationToken == null)
            {
                membership.PasswordVerificationToken = GenerateToken();
                membership.PasswordVerificationTokenExpirationDate = DateTime.UtcNow.AddMinutes(tokenExpirationInMinutesFromNow);
                dbContext.SaveChanges();
            }
            return membership.PasswordVerificationToken;
        }

        private webpages_membership getConfirmedUser(string userName)
        {
            var rsl = (from u in userProfiles
                    join m in memberships on u.UserId equals m.UserId
                    where m.IsConfirmed == true && u.UserName == userName
                    select m).FirstOrDefault();
            return rsl;
        }

        public override ICollectionGetAccountsForUser(string userName)
        {
            var rsl = new List();

            foreach (var oAuth in from o in oAuthMemberships
                                  join u in userProfiles on o.UserId equals u.UserId
                                  where u.UserName == userName
                                  select o)
            {
                rsl.Add(new OAuthAccountData(oAuth.Provider, oAuth.ProviderUserId));
            }

            return rsl;
        }

        public override DateTime GetCreateDate(string userName)
        {
            var membership = (from m in memberships
                              join u in userProfiles on m.UserId equals u.UserId
                              where u.UserName == userName
                              select m).FirstOrDefault();
            return membership == null ? DateTime.MinValue : membership.CreateDate.Value;
        }

        public override DateTime GetLastPasswordFailureDate(string userName)
        {
            var membership = (from m in memberships
                              join u in userProfiles on m.UserId equals u.UserId
                              where u.UserName == userName
                              select m).FirstOrDefault();
            return membership == null || membership.LastPasswordFailureDate.HasValue ?
                DateTime.MinValue : membership.LastPasswordFailureDate.Value;
        }

        public override DateTime GetPasswordChangedDate(string userName)
        {
            var membership = (from m in memberships
                              join u in userProfiles on m.UserId equals u.UserId
                              where u.UserName == userName
                              select m).FirstOrDefault();
            return membership == null || membership.PasswordChangedDate.HasValue ?
                DateTime.MinValue : membership.PasswordChangedDate.Value;
        }

        public override int GetPasswordFailuresSinceLastSuccess(string userName)
        {
            var membership = (from m in memberships
                              join u in userProfiles on m.UserId equals u.UserId
                              where u.UserName == userName
                              select m).FirstOrDefault();
            return membership == null ? -1 : membership.PasswordFailuresSinceLastSuccess;
        }

        public override int GetUserIdFromPasswordResetToken(string token)
        {
            var user = (from m in memberships
                        where m.PasswordVerificationToken == token
                        select m).FirstOrDefault();
            return user == null ? -1 : user.UserId;
        }

        public override bool IsConfirmed(string userName)
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");

            return getConfirmedUser(userName) != null;
        }

        public override bool ResetPasswordWithToken(string token, string newPassword)
        {
            if (string.IsNullOrEmpty(newPassword))
                throw new ArgumentNullException("newPassword");

            var user = (from m in memberships
                        where m.PasswordVerificationToken == token && m.PasswordVerificationTokenExpirationDate > DateTime.UtcNow
                        select m).FirstOrDefault();

            if (user == null)
                return false;

            user.Password = Crypto.HashPassword(newPassword);
            user.PasswordSalt = string.Empty;
            user.PasswordChangedDate = DateTime.UtcNow;
            user.PasswordVerificationToken = null;
            user.PasswordVerificationTokenExpirationDate = null;
            dbContext.SaveChanges();

            return true;
        }

        public override string ApplicationName
        {
            get
            {
                if (preProvider == null)
                    throw new NotSupportedException();
                return preProvider.ApplicationName;
            }
            set
            {
                if (preProvider == null)
                    throw new NotSupportedException();
                preProvider.ApplicationName = value;
            }
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            if (preProvider == null) throw new NotSupportedException();
            return preProvider.ChangePassword(username, oldPassword, newPassword);
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            if (preProvider == null) throw new NotSupportedException();
            return preProvider.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);
        }

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
        string passwordAnswer, bool isApproved, object providerUserKey, out System.Web.Security.MembershipCreateStatus status)
        {
            if (preProvider == null) throw new NotSupportedException();
            return preProvider.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            if (preProvider != null)
                return preProvider.DeleteUser(username, deleteAllRelatedData);

            foreach (var u in (from u in userProfiles where u.UserName == username select u))
                userProfiles.Remove(u);

            dbContext.SaveChanges();
            return true;
        }

        public override bool EnablePasswordReset
        {
            get { return preProvider != null && preProvider.EnablePasswordReset; }
        }

        public override bool EnablePasswordRetrieval
        {
            get { return preProvider != null && preProvider.EnablePasswordRetrieval; }
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            if (preProvider != null)
                return preProvider.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords);
            else
                throw new NotSupportedException();
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            if (preProvider != null)
                return preProvider.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords);
            else
                throw new NotSupportedException();
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            if (preProvider != null)
                return preProvider.GetAllUsers(pageIndex, pageSize, out totalRecords);
            else
                throw new NotSupportedException();
        }

        public override int GetNumberOfUsersOnline()
        {
            if (preProvider != null)
                return preProvider.GetNumberOfUsersOnline();
            else
                throw new NotSupportedException();
        }

        public override string GetPassword(string username, string answer)
        {
            if (preProvider != null)
                return preProvider.GetPassword(username, answer);
            else
                throw new NotSupportedException();
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            if (preProvider != null)
                return preProvider.GetUser(username, userIsOnline);

            var user = (from u in userProfiles
                        join m in memberships on u.UserId equals m.UserId
                        where u.UserName == username
                        select new
                        {
                            UserId = u.UserId,
                            UserName = u.UserName,
                            CreateDate = m.CreateDate,
                            PasswordChangeDate = m.PasswordChangedDate
                        }).FirstOrDefault();
            return user == null ? null : new MembershipUser(Membership.Provider.Name,
                username, user.UserId, null, null, null, true, false, user.CreateDate.Value,
                DateTime.MinValue, DateTime.MinValue, user.PasswordChangeDate.Value, DateTime.MinValue);
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            if (preProvider != null)
                return preProvider.GetUser(providerUserKey, userIsOnline);

            throw new NotSupportedException();
        }

        public override string GetUserNameByEmail(string email)
        {
            if (preProvider == null)
                throw new NotSupportedException();

            return preProvider.GetUserNameByEmail(email);
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { return preProvider == null ? int.MaxValue : preProvider.MaxInvalidPasswordAttempts; }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { return preProvider == null ? 0 : preProvider.MinRequiredNonAlphanumericCharacters; }
        }

        public override int MinRequiredPasswordLength
        {
            get { return preProvider == null ? 0 : preProvider.MinRequiredPasswordLength; }
        }

        public override int PasswordAttemptWindow
        {
            get { return preProvider == null ? int.MaxValue : preProvider.PasswordAttemptWindow; }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { return preProvider == null ? MembershipPasswordFormat.Hashed : preProvider.PasswordFormat; }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { return preProvider == null ? string.Empty : preProvider.PasswordStrengthRegularExpression; }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { return preProvider != null && preProvider.RequiresQuestionAndAnswer; }
        }

        public override bool RequiresUniqueEmail
        {
            get { return preProvider != null && preProvider.RequiresUniqueEmail; }
        }

        public override string ResetPassword(string username, string answer)
        {
            if (preProvider == null)
                throw new NotSupportedException();

            return preProvider.ResetPassword(username, answer);
        }

        public override bool UnlockUser(string userName)
        {
            if (preProvider == null)
                throw new NotSupportedException();

            return preProvider.UnlockUser(userName);
        }

        public override void UpdateUser(MembershipUser user)
        {
            if (preProvider == null)
                throw new NotSupportedException();

            preProvider.UpdateUser(user);
        }

        public override bool ValidateUser(string username, string password)
        {
            if (preProvider != null)
                return preProvider.ValidateUser(username, password);

            if (string.IsNullOrEmpty(username))
                throw new ArgumentNullException("username");

            if (string.IsNullOrEmpty(password))
                throw new ArgumentNullException("password");

            var user = getConfirmedUser(username);
            if (user == null)
                return false;

            var rsl = user.Password != null && Crypto.VerifyHashedPassword(user.Password, password);
            if (rsl)
                user.PasswordFailuresSinceLastSuccess = 0;
            else
            {
                user.PasswordFailuresSinceLastSuccess += 1;
                user.LastPasswordFailureDate = DateTime.UtcNow;
            }
            dbContext.SaveChanges();
            return rsl;
        }

        public override bool HasLocalAccount(int userId)
        {
            return (from m in memberships where m.UserId == userId select m).Any();
        }

        public override void CreateOrUpdateOAuthAccount(string provider, string providerUserId, string userName)
        {
            if (string.IsNullOrEmpty(userName))
                throw new MembershipCreateUserException(MembershipCreateStatus.ProviderError);

            var user = (from u in userProfiles where u.UserName == userName select u).FirstOrDefault();
            if (user == null)
                throw new MembershipCreateUserException(MembershipCreateStatus.InvalidUserName);

            var oAuthUser = (from o in oAuthMemberships where o.Provider == provider.ToUpperInvariant()
            && o.ProviderUserId == providerUserId.ToUpperInvariant() select o).FirstOrDefault();
            if (oAuthUser == null)
            {
                oAuthMemberships.Add(new webpages_oauthmembership()
                {
                    Provider = provider.ToUpperInvariant(),
                    ProviderUserId = providerUserId.ToUpperInvariant(),
                    UserId = user.UserId
                });
            }
            else
            {
                oAuthUser.UserId = user.UserId;
            }
            dbContext.SaveChanges();
        }

        public override void DeleteOAuthAccount(string provider, string providerUserId)
        {
            foreach (var oauth in (from o in oAuthMemberships where o.ProviderUserId == providerUserId.ToUpperInvariant()
            && o.Provider == providerUserId.ToUpperInvariant() select o))
                oAuthMemberships.Remove(oauth);
            dbContext.SaveChanges();
        }

        public override void DeleteOAuthToken(string token)
        {
            foreach (var t in (from o in dbContext.webpages_oauthtoken where o.Token == token select o))
                dbContext.webpages_oauthtoken.Remove(t);

            dbContext.SaveChanges();
        }

        public override string GetOAuthTokenSecret(string token)
        {
            var secret = (from o in dbContext.webpages_oauthtoken where o.Token == token select o).FirstOrDefault();
            return secret == null ? null : secret.Secret;
        }

        public override string GetUserNameFromId(int userId)
        {
            var user = (from u in userProfiles where u.UserId == userId select u).FirstOrDefault();
            return user == null ? null : user.UserName;
        }

        public override int GetUserIdFromOAuth(string provider, string providerUserId)
        {
            var user = (from u in oAuthMemberships
                        where u.Provider == provider.ToUpperInvariant() && u.ProviderUserId == provider.ToUpperInvariant()
                        select u).FirstOrDefault();
            return user == null ? -1 : user.UserId;
        }

        public override void ReplaceOAuthRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                foreach (var oauth in (from o in dbContext.webpages_oauthtoken where o.Token == requestToken select o))
                    dbContext.webpages_oauthtoken.Remove(oauth);

                dbContext.SaveChanges();

                StoreOAuthRequestToken(accessToken, accessTokenSecret);
                ts.Complete();
            }
        }

        public override void StoreOAuthRequestToken(string requestToken, string requestTokenSecret)
        {
            var secret = (from oauth in dbContext.webpages_oauthtoken where oauth.Token == requestToken select oauth).FirstOrDefault();
            if (secret == null)
            {
                dbContext.webpages_oauthtoken.Add(new webpages_oauthtoken()
                {
                    Token = requestToken,
                    Secret = requestTokenSecret
                });
            }
            else
            {
                secret.Secret = requestTokenSecret;
            }
            dbContext.SaveChanges();
        }

    }
}

然后是 RoleProvider 的代码。

using System;
using System.Collections.Generic;
using System.Data.Linq.SqlClient;
using System.Globalization;
using System.Linq;
using System.Resources;
using System.Transactions;
using System.Web;
using System.Web.Security;

namespace TestSimpleMembership.Help
{
    public class MySqlSimpleRoleProvider : RoleProvider
    {
        private static string Security_NoUserFound = "No user was found that has the name "{0}".";

        private static string SimpleRoleProvder_UserNotInRole = "User "{0}" is not in role "{1}".";
        private static string SimpleRoleProvder_UserAlreadyInRole = "User "{0}" is already in role "{1}".";
        private static string SimpleRoleProvider_RoleExists = "Role "{0}" already exists.";
        private static string SimpleRoleProvder_RolePopulated = "The role "{0}" cannot be deleted because there are still users in the role.";
        private static string SimpleRoleProvider_NoRoleFound = "No role was found that has the name "{0}".";

        private static string DEFAULT_PROVIDER_NAME = "MySQLRoleProvider";
        private static string DEFAULT_NAME = "MySqlSimpleRoleProvider";
        private static string DEFAULT_PROVIDER_CONFIG_NAME = "provider";

        private RoleProvider preProvider;
        private MemberAuthorContext dbContext;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (config == null) throw new ArgumentNullException("config");
            if (string.IsNullOrEmpty(name)) name = DEFAULT_NAME;
            base.Initialize(name, config);

            var providerName = config[DEFAULT_PROVIDER_CONFIG_NAME];
            if (!string.IsNullOrEmpty(providerName))
                this.preProvider = Roles.Providers[providerName] ?? Roles.Providers[DEFAULT_PROVIDER_NAME];

            this.dbContext = new MemberAuthorContext();
        }

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            if (preProvider != null)
            {
                preProvider.AddUsersToRoles(usernames, roleNames);
                return;
            }

            var users = getUserFromNames(usernames);

            var roles = getRoleFromNames(roleNames);

            foreach (var user in users)
            {
                foreach (var role in roles)
                {
                    if (IsUserInRole(user.UserName, role.RoleName))
                        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                        SimpleRoleProvder_UserAlreadyInRole, new object[] { user.UserName, role.RoleName }));

                    dbContext.webpages_usersinroles.Add(new webpages_usersinroles()
                    {
                        UserId = user.UserId,
                        RoleId = role.RoleId
                    });

                }
            }
            dbContext.SaveChanges();
        }

        private ListgetRoleFromNames(string[] roleNames)
        {
            var roles = new List();
            foreach (var name in roleNames)
            {
                var role = (from r in dbContext.webpages_roles where r.RoleName == name select r).FirstOrDefault();
                if (role == null)
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                        SimpleRoleProvider_NoRoleFound, new object[] { name }));
                roles.Add(role);
            }
            return roles;
        }

        private ListgetUserFromNames(string[] usernames)
        {
            var users = new List();
            foreach (var name in usernames)
            {
                var user = (from u in dbContext.userprofile where u.UserName == name select u).FirstOrDefault();
                if (user == null)
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                        Security_NoUserFound, new object[] { name }));
                users.Add(user);
            }
            return users;
        }

        public override string ApplicationName
        {
            get
            {
                if (preProvider == null)
                    throw new NotSupportedException();
                return preProvider.ApplicationName;
            }
            set
            {
                if (preProvider == null)
                    throw new NotSupportedException();
                preProvider.ApplicationName = value;
            }
        }

        public override void CreateRole(string roleName)
        {
            if (preProvider != null)
            {
                preProvider.CreateRole(roleName);
                return;
            }

            if ((from r in dbContext.webpages_roles where r.RoleName == roleName select r).Any())
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                    SimpleRoleProvider_RoleExists, new object[] { roleName }));

            dbContext.webpages_roles.Add(new webpages_roles() { RoleName = roleName });
            dbContext.SaveChanges();
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            if (preProvider != null)
                return preProvider.DeleteRole(roleName, throwOnPopulatedRole);

            var role = (from r in dbContext.webpages_roles where r.RoleName == roleName select r).FirstOrDefault();
            if (role == null)
                return false;

            var uirs = from uir in dbContext.webpages_usersinroles where uir.RoleId == role.RoleId select uir;
            if (throwOnPopulatedRole && uirs.Any())
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                    SimpleRoleProvder_RolePopulated, new object[] { roleName }));

            using (TransactionScope ts = new TransactionScope())
            {
                foreach (var uir in uirs)
                    dbContext.webpages_usersinroles.Remove(uir);
                dbContext.webpages_roles.Remove(role);
                dbContext.SaveChanges();
                ts.Complete();
            }
            return true;
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            if (preProvider != null)
                return preProvider.FindUsersInRole(roleName, usernameToMatch);

            return (from u in dbContext.userprofile
                    join uir in dbContext.webpages_usersinroles on u.UserId equals uir.UserId
                    join r in dbContext.webpages_roles on uir.RoleId equals r.RoleId
                    where r.RoleName == roleName && SqlMethods.Like(u.UserName, usernameToMatch)
                    select u.UserName).ToArray();
        }

        public override string[] GetAllRoles()
        {
            if (preProvider != null)
                return preProvider.GetAllRoles();

            return (from r in dbContext.webpages_roles select r.RoleName).ToArray();
        }

        public override string[] GetRolesForUser(string username)
        {
            if (preProvider != null)
                return preProvider.GetRolesForUser(username);

            return (from r in dbContext.webpages_roles
                    join uir in dbContext.webpages_usersinroles on r.RoleId equals uir.RoleId
                    join u in dbContext.userprofile on uir.UserId equals u.UserId
                    where u.UserName == username
                    select r.RoleName).Distinct().ToArray();
        }

        public override string[] GetUsersInRole(string roleName)
        {
            if (preProvider != null)
                return preProvider.GetUsersInRole(roleName);

            return (from u in dbContext.userprofile
                    join uir in dbContext.webpages_usersinroles on u.UserId equals uir.UserId
                    join r in dbContext.webpages_roles on uir.RoleId equals r.RoleId
                    where r.RoleName == roleName
                    select u.UserName).ToArray();
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            if (preProvider != null)
                return preProvider.IsUserInRole(username, roleName);

            return (from u in dbContext.userprofile
                    join uir in dbContext.webpages_usersinroles on u.UserId equals uir.UserId
                    join r in dbContext.webpages_roles on uir.RoleId equals r.RoleId
                    where u.UserName == username && r.RoleName == roleName
                    select u).Any();
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            if (preProvider != null)
            {
                preProvider.RemoveUsersFromRoles(usernames, roleNames);
                return;
            }

            foreach (var name in roleNames)
            {
                if (!RoleExists(name))
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                        SimpleRoleProvider_NoRoleFound, new object[] { name }));
            }

            foreach (var user in usernames)
            {
                foreach (var role in roleNames)
                {
                    if (!IsUserInRole(user, role))
                        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                            SimpleRoleProvder_UserNotInRole, new object[] { user, role }));
                }
            }

            var users = getUserFromNames(usernames);
            var roles = getRoleFromNames(roleNames);

            foreach (var user in users)
            {
                foreach (var role in roles)
                {
                    dbContext.webpages_usersinroles.Remove((from uir in dbContext.webpages_usersinroles
                                                            where uir.RoleId == role.RoleId && uir.UserId == user.UserId
                                                            select uir).FirstOrDefault());
                }
            }
            dbContext.SaveChanges();
        }

        public override bool RoleExists(string roleName)
        {
            if (preProvider != null)
                return preProvider.RoleExists(roleName);

            return (from r in dbContext.webpages_roles where r.RoleName == roleName select r).Any();
        }

    }
}

以上代码可以看出,如果你指定了原来的 Membership 系统的 Provider 的话,其实两个认证系统是可以整合在一起的。

时间: 2024-10-02 01:18:51

SimpleMembershipProvider 的 MySql 实现的相关文章

记一次MySQL找回用户数据

事情经过 有天,我们公司外区的一个销售C说他8月3号以前的工作流记录找不到了.问清缘由,原来是更新了微信号(我们公司的工作流是基于企业微信开发的).经过分析,微信号和流程数据并没什么关系,所以初步得出结论:本来只需要更新微信号的,结果我们公司的流程系统管理员把用户先删除,再创建了新的用户. 解决过程 1.首先想到的是直接从定时备份数据里面找回原来的用户ID,结果发现系统只备份了十天的记录,而工作流系统上显示销售C只有8月3号以后的流程记录,距今已经40多天,从自动备份的数据里已经无法恢复. 2.

centos7下使用yum安装mysql

CentOS7的yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql的repo源. 1. 下载mysql的repo源 $ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 2. 安装mysql-community-release-el7-5.noarch.rpm包 $ sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm 安装这个

EF+mvc+mysql

这个真是一个大坑啊.TM折腾了一下午终于弄好了.赶紧记录下来分享给大家,免得有和我一样一直配置不成功的又折腾半天-.1.安装MySQL for Visual Studio这个直接在mysql官网下载并安装就好了.不过这个必须是vs2013 professional版本以上才可以!!2.安装MySQL Connector/Net这个可以可以通过NuGet工具获得,比较轻松愉快,当然你也可以自己下载,自己引用.3.配置web.config.首先是connectionStrings节点 1 <conn

Linux环境下MySQL数据库用SQL语句插入中文显示 “问号或者乱码 ” 问题解决!

问题: 在普通用户权限下执行 mysql -u root -p进入mysql数据库,中间步骤省略,插入数据:insert into 库名(属性)values('汉字'); 会出现如下提示:  Query OK, 1 row affected, 1 warning (0.00 sec)    表明出现错误,没有插入成功,然后执行select * from 表名   就会出现如下的问题:显示的表中出现乱码或者问号. 如图: 解决方案: 首先重新打开一个终端窗口(方便操作),进入root用户模式 执行

Centos6.5 zabbix3.2.6监控mysql

  一.     操作环境 我使用的linux系统是centos6.5,数据库是mysql5.6,apache2.4,php5,6 安装目录: /usr/local/apache /usr/local/php /usr/local/mysql /usr/local/zabbix Zabbix服务器插件安装 Zabbix3.2.6自带监控mysql模板监控项不全面,所以重新下载导入到zabbix里面 下载网址:. https://www.percona.com/downloads/percona-

MySQL数据库基础知识

day02 MySQL数据库基础知识 一.基础知识概述: 基础决定你这门课程的学习成败!只有学习好这些基础知识以后,你才能真正的运用自如.才能够对数据库有更深入的了解,道路才会越走越远. 二.基础知识: 1.数据库(database):数据库就好比是一个物理的文档柜,一个容器,把我们整理好的数据表等等归纳起来. 创建数据库命令:        create database 数据库名; 2.查看数据库         show databases; 3.打开指定的数据库         use 

MariaDB(MySQL)创建、删除、选择及数据类型使用详解

一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品.在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB. MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL A

Mac配置Mysql遇到的 --secure-file-priv问题

1.安装mysql 在官网上安装,一步步无障碍安装(但根据后来文件入法导入/导出的经验,最好在安装前设置secure-file-priv为empty,5.7.6之后似乎就默认为NULL,而secure-file-prive为NULL的话,就不支持文件导入/出) 2.安装navicat premimum 在网上找到一个破解版,按照破解步骤来安装,很好用 3.遇到的问题:在将选择的记录导出到.csv文件时,出现提示"The MySQL server is running with the --sec

MySQL(九)之数据表的查询详解(SELECT语法)二

上一篇讲了比较简单的单表查询以及MySQL的组函数,这一篇给大家分享一点比较难得知识了,关于多表查询,子查询,左连接,外连接等等.希望大家能都得到帮助! 在开始之前因为要多表查询,所以搭建好环境: 1)创建数据表suppliers 前面已经有一张表是book表,我们在建立一张suppliers(供应商)表和前面的book表对应. 也就是说 让book中s_id字段值指向suppliers的主键值,创建一个外键约束关系. 其实这里并没有达到真正的外键约束关系,只是模拟,让fruits中的s_id中