Можно ли изменить имя пользователя с помощью API членства

Я использую поставщик членства sql по умолчанию с ASP.NET, и я хотел бы предоставить страницу для изменения имени пользователя. Я уверен, что могу сделать это с помощью специального поставщика, но можно ли это сделать с помощью поставщика по умолчанию?

Вторая часть моего вопроса: следует ли разрешить пользователям изменять свое имя пользователя после создания учетной записи?


person Bobby Ortiz    schedule 16.06.2009    source источник


Ответы (7)


Верно, что поставщик членства в SQL по умолчанию не позволяет изменять имя пользователя. Однако нет никаких внутренних причин, чтобы запретить пользователям изменять свои имена пользователей, если у вас есть действительный аргумент на вашем сайте, чтобы разрешить это. Ни одна из таблиц в базе данных SQL не имеет имени пользователя в качестве ключа, все основано на идентификаторе пользователя, поэтому с точки зрения реализации это было бы довольно просто.

person Jonathan Freeland    schedule 16.06.2009
comment
Хотя таблицы db основаны на отдельном ключе UserID, SP, которые запускает поставщик членства .NET, основаны на имени пользователя. Я не слишком внимательно изучал источник, но, похоже, это указывает на то, что если вы измените имя пользователя, последующие операции членства могут завершиться неудачно (попытка использовать старое имя пользователя). - person Toby; 22.06.2011
comment
Беспокойство Тоби не проблема? Похоже, что некоторые SP могут выйти из строя, это довольно серьезная причина НЕ принимать ответ и не использовать его до тех пор, пока он не будет проверен. Есть предположения? - person dnord; 03.11.2011
comment
Если ваш код все еще передает устаревшие имена пользователей провайдеру после обновления, то Тоби прав, у вас, очевидно, будут проблемы. В остальном никаких побочных эффектов нет. - person Jonathan Freeland; 03.11.2011

Если вы используете SqlMembershipProvider, вы можете расширить его - это также относится к этому вопросу.
Roadkill - это вики-движок, а не описание моего стиля программирования.

using System;
using System.Web.Security;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
using System.Web.Configuration;

namespace Roadkill.Core
{
    public class RoadkillMembershipProvider : SqlMembershipProvider
    {
        private string _connectionString;

        protected string ConnectionString
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_connectionString))
                {
                    Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
                    MembershipSection section = config.SectionGroups["system.web"].Sections["membership"] as MembershipSection;
                    string defaultProvider = section.DefaultProvider;
                    string connstringName = section.Providers[defaultProvider].ElementInformation.Properties["connectionStringName"].Value.ToString();
                    _connectionString = config.ConnectionStrings.ConnectionStrings[connstringName].ConnectionString;
                }

                return _connectionString;
            }
        }

        public bool ChangeUsername(string oldUsername, string newUsername)
        {
            if (string.IsNullOrWhiteSpace(oldUsername))
                throw new ArgumentNullException("oldUsername cannot be null or empty");

            if (string.IsNullOrWhiteSpace(newUsername))
                throw new ArgumentNullException("newUsername cannot be null or empty");

            if (oldUsername == newUsername)
                return true;

            using (SqlConnection connection = new SqlConnection(ConnectionString))
            {
                connection.Open();

                using (SqlCommand command = connection.CreateCommand())
                {
                    command.CommandText = "UPDATE aspnet_Users SET UserName=@NewUsername,LoweredUserName=@LoweredNewUsername WHERE UserName=@OldUsername";

                    SqlParameter parameter = new SqlParameter("@OldUsername", SqlDbType.VarChar);
                    parameter.Value = oldUsername;
                    command.Parameters.Add(parameter);

                    parameter = new SqlParameter("@NewUsername", SqlDbType.VarChar);
                    parameter.Value = newUsername;
                    command.Parameters.Add(parameter);

                    parameter = new SqlParameter("@LoweredNewUsername", SqlDbType.VarChar);
                    parameter.Value = newUsername.ToLower();
                    command.Parameters.Add(parameter);

                    return command.ExecuteNonQuery() > 0;
                }
            }
        }
    }
}
person Chris S    schedule 27.02.2011
comment
@russau да, я поместил это в аннотации данных в доменном объекте. Любое место хорошее, хотя - person Chris S; 24.05.2011
comment
Как вы называете этот метод? Я предполагаю, что api членства - это то, что есть, поэтому я понимаю, что метод мог бы с таким же успехом (или лучше) жить в классе, который не унаследовал SqlMembershipProvider. - person Carl R; 25.07.2011
comment
@Carl, вам нужно преобразовать вашего поставщика по умолчанию в RoadkillMembershipProvider, сначала проверяя, что он относится к этому типу - person Chris S; 25.07.2011

У Скотта Митчелла есть отличная статья, описывающая, как справиться с этой ситуацией здесь: http://www.4guysfromrolla.com/articles/070109-1.aspx.

Важная цитата из его статьи:

К сожалению, идеализм и прагматизм пересекаются редко. В некоторых случаях, например при разрешении пользователю изменить свое имя пользователя, у нас нет другого выбора, кроме как работать напрямую с базовым хранилищем данных.

Он также показывает, как повторно аутентифицировать пользователя после изменения его имени пользователя / электронной почты.

person Nathan Prather    schedule 28.08.2012

Если вы хотите сделать это с помощью API членства, кажется, что правильный способ будет выглядеть так:

http://omaralzabir.com/how_to_change_user_name_in_asp_net_2_0_membership_provider/

По сути, вам нужно сделать следующее (для полноты я скопировал из приведенной выше ссылки):

  1. Создайте нового пользователя, используя новый адрес электронной почты
  2. Получите пароль старой учетной записи и установите его для новой учетной записи. Если вы не можете получить старый пароль через поставщика услуг членства, спросите пользователя.
  3. Создайте новый профиль для новой учетной записи пользователя
  4. Скопируйте все свойства из старого профиля в новый объект профиля.
  5. Выйти пользователя из старой учетной записи
  6. Автоматический вход в новую учетную запись, чтобы пользователь не заметил, что только что произошло.
person Leandro Gomide    schedule 01.11.2010
comment
Я бы посоветовал не делать это таким образом: если у вас есть другие вещи, привязанные к UserID, вы рискуете потерять пользовательский контент (особенно по мере развития вашей системы и новых вещей, зависящих от userID). - person Arve Systad; 10.12.2014

Поскольку API-интерфейс Membershiop не позволяет напрямую изменять имя пользователя, вы можете напрямую обращаться к таблице aspnet_Membership в своей базе данных.

person wlegend    schedule 29.12.2011

Вот версия, которая включает Enterprise Libraries DAB и пару других незначительных изменений. Кроме того, я не вижу смысла возвращать логическое значение, поскольку оно либо завершается успешно, либо генерирует исключение.

        public static void ChangeUsername(string oldUsername, string newUsername)
    {
        if (string.IsNullOrWhiteSpace(oldUsername))
        {
            throw new ArgumentNullException("oldUsername cannot be null or empty");
        }

        if (string.IsNullOrWhiteSpace(newUsername))
        {
            throw new ArgumentNullException("newUsername cannot be null or empty");
        }

        if (oldUsername.Equals(newUsername))
        {
            return;
        }

        Database db = DatabaseFactory.CreateDatabase();
        using (DbCommand cmd = db.GetSqlStringCommand("UPDATE dbo.aspnet_Users SET UserName=@NewUsername, LoweredUserName=@LoweredNewUsername WHERE UserName=@OldUsername"))
        {
            db.AddInParameter(cmd, "@OldUsername", DbType.String, oldUsername);
            db.AddInParameter(cmd, "@NewUsername", DbType.String, newUsername);
            db.AddInParameter(cmd, "@LoweredNewUsername", DbType.String, newUsername.ToLower());

            db.ExecuteNonQuery(cmd);                
        }
    }
person LawMan    schedule 17.02.2014

Нет, класс MembershipUser не позволяет изменять свойство Username, поэтому вы не можете этого сделать.

На практике вы не должны позволять изменять имя пользователя. Если вы как-то позволите это сделать, то он потеряет свое предназначение и природу.

person this. __curious_geek    schedule 16.06.2009
comment
В итоге я написал своего собственного провайдера. потом я добавил эту способность. - person Bobby Ortiz; 07.12.2009
comment
он совершенно не теряет своей цели или природы. Допустим, вы создали [email protected] для учетной записи. ой ты выродок ошибся! теперь ты полностью облажался. клиенты будут делать это ВСЕГДА. если вы используете электронную почту как логин, у вас проблема - person Simon_Weaver; 07.01.2010
comment
Почему бы вам не позволить кому-то изменить свое имя пользователя? Он не используется для однозначной идентификации пользователей в хранилище членства, как было сказано в комментариях выше. Что делать, если ваш клиент допустил опечатку в своем имени и хочет его исправить. - person Stephanvs; 18.02.2013