Каковы последствия использования одного MembershipProvider для аутентификации на нескольких серверах веб-служб? - PullRequest
2 голосов
/ 04 февраля 2011

В этом гипотетическом сценарии есть веб-приложение ASP.NET 4, которое одновременно объединяет данные из нескольких веб-служб.Все веб-сервисы имеют одинаковую реализацию, но являются отдельными экземплярами и не знают друг друга.

В веб-приложении пользователь предоставляет учетные данные для каждого веб-сервиса, к которому он хочет получить доступ, и процесс аутентификации повторяется.через все его комбинации имени пользователя и пароля в сочетании с URL для каждого веб-сервиса.(Неуклюжий пользовательский интерфейс предназначен только для иллюстрации ....)

Предположим, что веб-приложение использует метод ValidateUser в пользовательском классе MembershipProvider для аутентификации, а MembershipProvider настроен в web.config как обычно.

Предположим также, что пользовательский класс MembershipProvider имеет свойство Url, которое изменяется при каждом вызове аутентификации для различных веб-служб.

Предполагается, чтовсе это, как вы справляетесь со сценарием, когда пользователь 1 и пользователь 2 проходят аутентификацию одновременно, но пользователь 1 имеет доступ к веб-службе A, B и C, а пользователь 2 имеет доступ к веб-службе X, Y,и Z?

Будут ли перепутаны учетные данные и URL-адреса, и пользователь 1 может увидеть данные пользователя 2 и наоборот?

1 Ответ

3 голосов
/ 04 февраля 2011

Если вы собираетесь внедрить пользовательского провайдера членства, вы увидите много головных болей в будущем. Причина в том, что в модели вашего приложения схема авторизации основана на членстве пользователя (для определенной службы).

Я бы посоветовал иметь ваше собственное членство (для вашего собственного сайта) и расширить модель профиля, чтобы вы могли получать учетные данные для каждой службы, к которой у пользователя есть доступ прямо из профиля пользователя.

Информация профиля может использоваться вместе с вашей собственной авторизацией на основе вашего собственного членства и поставщиков ролей (специфично для вашего сайта). В этом случае вы можете назначить каждому пользователю определенную роль для каждой службы.

Чтобы успешно добиться этого, для каждой службы напишите обертку, инкапсулирующую вызовы службы собственными методами (которые вызывают службу). Это позволит вам пометить ваши собственные методы с атрибутом [PrincipalPermissison] ... и получить непревзойденную авторизацию.

Таким образом, если у вашего пользователя есть доступ к веб-службе Amazon, и в его / ее профиле есть учетные данные для этой службы, вы можете указать следующее:

Роль пользователя: "AmazonAccessor"

public AmazonServiceWrapper
{
    [PrincipalPermission(SecurityAction.Demand, Role = "AmazonAccessor")]
    public void DoSomething()
    {
        UserProfile profile = UserProfile.Get();
        ServiceCredential credential = (ServiceCredential)(from c in profile.ServiceCredentials where c.ServiceName = "Amazon" select c).Take(1);

        if( credential == null )
            return;

        AmazonService amazon = new AmazonService();
        amazon.ClientCredentials.UserName.UserName = credential.Username; //coming from profile
        amazon.ClientCredentials.UserName.Password = credential.Password; //coming from profile

        try{
            amazon.DoSomething(); //wrap the amazon call.
        }
        catch(Exception ex)
        {

        }
    }
}

Это избавит вас от необходимости совмещать членство и всякие другие головные боли.

Теперь, чтобы создать свой собственный профиль, вы можете сделать что-то вроде этого:

[Serializable]
public class ServiceCredential
{
    public string ServiceName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string ServiceUrl { get; set; }
}

public class UserProfile : ProfileBase
{
    public static UserProfile Get(string username)
    {
        return (UserProfile)Create(username);
    }

    public static UserProfile Get()
    {
        return (UserProfile)Create(Membership.GetUser().UserName);
    }

    [SettingsAllowAnonymous(false)]
    public List<ServiceCredential> ServiceCredentials
    {
        get
        {
            try
            {
                return base.GetPropertyValue("ServiceCredentials") as List<ServiceCredential>;
            }
            catch
            {
               return new List<ServiceCredential>();
            }
        }
        set
        {
            base.SetPropertyValue("ServiceCredentials", value);
        }
    }
}

И, конечно, веб-конфиг:

<system.Web>
<profile 
   inherits="MyApplication.UserProfile" 
   defaultProvider="AspNetSqlProfileProvider">
   <providers>
      <add 
          name="MyProfileProvider" 
          type="System.Web.Profile.SqlProfileProvider"
          connectionStringName="MyConnectionString"
          applicationName="MyApplication" />
   </providers>
</profile>
<system.Web>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...