在Asp.Net Membership中手动更改用户名

5
我可以通过直接访问asp.net成员表来更改用户名。然而,旧的用户名会被保留在一个新行中,并由asp.net自动分配一个新的用户ID。我该如何阻止这种情况发生?(注:仅适用于用户表和角色表,不适用于成员表。)
var mUser = dc.aspnet_Users
            .Where(u => u.UserId == (Guid)user.ProviderUserKey)
            .Select(u => u).SingleOrDefault();

mUser.UserName = newName;
mUser.LoweredUserName = newName.ToLower();

try
{
    dc.SubmitChanges();
}
catch
{
    ...
}

我已经解决了,似乎问题出在为用户旧名称的旧成员对象分配角色上。因此,新的角色行被自动添加,并由角色类创建了一个用户ID。 - zsharp
那么,你做了什么来解决这个问题? - CompanyDroneFromSector7G
3个回答

10

在ASP.NET 2.0中,SQL成员资格提供程序不支持更改用户名。您仍然可以更改用户名,但必须使用自定义实现。

此外,您必须使用新的用户名更新成员身份验证 cookie,以避免使用相同用户名但新的用户ID重新创建用户。

在下面的示例中,我使用Linq to SQL来更新成员身份验证表 - 我有一个名为MembershipDataContext的数据上下文。

public bool ChangeUserName(Guid userId, string newUserName)
{
    bool success = false;
    newUserName = newUserName.Trim();

    // Make sure there is no user with the new username
    if (Membership.GetUser(newUserName) == null)
    {
        MembershipUser u = Membership.GetUser(userId);
        string oldUsername = u.UserName;
        // get current application

        MembershipDataContext context = new MembershipDataContext ();
        aspnet_User userToChange = (from user in context.aspnet_Users
                                    where user.UserId == userId
                                    select user).FirstOrDefault();

        if (userToChange != null)
        {
            userToChange.UserName = newUserName;
            userToChange.LoweredUserName = newUserName.ToLower();

            context.SubmitChanges();

            // ASP.NET Issues a cookie with the user name. 
            // When a request is made with the specified cookie, 
            // ASP.NET creates a row in aspnet_users table.
            // To prevent this sign out the user and then sign it in

            string cookieName = FormsAuthentication.FormsCookieName;
            HttpCookie authCookie = 
              HttpContext.Current.Request.Cookies[cookieName];

            FormsAuthenticationTicket authTicket = null;

            try
            {
                authTicket = 
                    FormsAuthentication.Decrypt(authCookie.Value);

                FormsIdentity formsIdentity = 
                    new FormsIdentity(
                        new FormsAuthenticationTicket(
                            authTicket.Version, 
                            newUserName, 
                            authTicket.IssueDate, 
                            authTicket.Expiration, 
                            authTicket.IsPersistent, 
                            authTicket.UserData));

                string y = HttpContext.Current.User.Identity.Name;
                string[] roles = 
                    authTicket.UserData.Split(new char[] { '|' });
                System.Security.Principal.GenericPrincipal genericPrincipal = 
                    new System.Security.Principal.GenericPrincipal(
                                                        formsIdentity, 
                                                        roles);

                HttpContext.Current.User = genericPrincipal;
            }
            catch (ArgumentException ex)
            {
                // Handle exceptions
            }
            catch( NullReferenceException ex)
            {
                // Handle exceptions
            }

            FormsAuthentication.SignOut();
            HttpContext.Current.Session.Abandon();
            FormsAuthentication.SetAuthCookie(newUserName, false);
            success = true;
        }
    }

    return success;
}

当您使用FormsAuthentication.setauthcookie时,不是已经为您创建了Cookie吗?为什么要像您所做的那样手动创建呢? - zsharp
我不手动设置 cookie,只是使用它来获取 FormsAuthenticationTicket 实例。 - Branislav Abadjimarinov
我的观点是我不明白为什么你需要获取票据的实例。如果您只是注销并重新登录,那不就足够了吗? - zsharp
我使用它来在同一请求中更新当前用户身份 - HttpContext.Current.User。如果我不这样做,它将返回旧的用户名。 - Branislav Abadjimarinov

1
你是怎么改变用户名的?我只是使用了一个更新 SQL 语句,更新了用户名而不是创建新行或保留旧用户名。
UPDATE [MyDatabase].[dbo].[aspnet_Users] 
SET [UserName] = 'mynewusername',
    [LoweredUserName] = LOWER('mynewusername')
WHERE [UserName] = 'myusername'

请提供更多细节。问题可能出在您用于更新的LINQ查询中。上面的SQL代码会更新用户名字段,而不会创建新记录。 - Ricardo Sanchez
我也使用了SQL语句运行了它,结果相同。 - zsharp
我无法在我的端上复制这个问题。如果可能的话,请尝试运行SQL Profiler来查看应用程序生成的实际SQL命令。 - Ricardo Sanchez
你是不是在使用角色? - zsharp

1

你必须同时更改UserName和LoweredUserName... 我假设API使用了另一个字段,进行了查找,观察到记录不存在(因为其中一个已更改),然后创建了一个新的记录。通常,它不会保留旧记录。

编辑:问题也可能是您正在通过ProviderUserKey字段查找账户吗?


我已经修改了两者。新的用户名可以正常工作,但表格中仍然有旧名称的附加行。(只在用户表和角色表中,而不在成员资格表中) - zsharp
问题可能出在你所查询的provideruserkey字段上吗?另外,你使用了SingleOrDefault,为什么没有进行null检查呢? - Brian Mains

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接