Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1706 / 243 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Лекция 9:

Промежуточная среда веб служб ASP.NET

Метод NewUser используется для добавления нового пользователя.

public void NewUser(string userName, string password, bool hashed)
{   
    if (Users.ContainsKey(userName))
    {
        throw new ApplicationException("Duplicate username.");
    }    
    if (hashed)
    {
        password = Utils.HashedPassword(password);
    }
    
    Users.Add(userName, password);
}

Методы Load и Save записывают список пользователей и их паролей (или их образов) в файл.

public static UsersList Load(string fileName)
{
    XmlSerializer serializer = new XmlSerializer(typeof(UsersList));   
    using (StreamReader reader = new StreamReader(fileName))
    {
        return (UsersList) serializer.Deserialize(reader);
    };
}    
    
public void Save(string fileName)    
{
    XmlSerializer serializer = new XmlSerializer(typeof(UsersList));    
    using (StreamWriter writer = new StreamWriter(fileName))
    {
        serializer.Serialize(writer, this);
    };
}
    }

Статический класс Utils облегчает вызов функции хеширования и преобразует ее результат в строку.

static class Utils
{
    public static string HashedPassword(string password)
    {
        SHA1CryptoServiceProvider crypto = new SHA1CryptoServiceProvider();

        byte[] inputBuffer =  Encoding.Unicode.GetBytes(password);
        return Convert.ToBase64String(crypto.ComputeHash(inputBuffer));
    }
}

Следующий make файл создает сборку расширения c менеджером пользователей и регистрирует ее в GAC после команды nmake && nmake install.

all: Seva.WS.UsersManager.dll

Seva.WS.UsersManager.dll: UsersManager.cs UsersManager.key
    csc /t:library /out:Seva.WS.UsersManager.dll 
	/keyfile:TimeAssertion.key /r:Microsoft.Web.Services3.dll UsersManager.cs

UsersManager.key:
    sn -k UsersManager.key

install:
    gacutil -nologo -i Seva.WS.UsersManager.dll

На стороне сервера в файле конфигурации ( web.config ) следует добавить информацию о менеджере учетных записей в элемент <microsoft.web.services3> <security>.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
  <microsoft.web.services3>
    <security>
      <securityTokenManager>
        <add type="Seva.WS.Users.UsersListManager, Seva.WS.UsersManager,
               Version=1.0.0.0, Culture=neutral, PublicKeyToken=..." 
             namespace=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
             localName="UsernameToken">
          <users file="C:\Inetpub\users.config"/>
        </add>
      </securityTokenManager>
    </security>
    <policy fileName="wse3policyCache.config" />
  </microsoft.web.services3>
</configuration>

Кроме процедуры установления идентичности пользователя, может существовать необходимость ограничить доступ к службе тех или иных пользователей. Для этого в разделе <policy><authorization> политики веб службы можно организовать список пользователей, используя элементы <allow> и <deny>.

Для посылки клиентом хеша пароля может использоваться описанное далее расширение UsernameClientAssertion. Оно может быть использовано для не представляющей критической важности веб службы, не использующей сертификаты X.509. Использование выданных или "самодельных" серверных сертификатов X.509 и открытых паролей в зашифрованном сообщении позволяет обеспечить гораздо большую степень безопасности.

[XmlRoot("user")]
public struct UserCredential
{
    [XmlAttribute("username")]    
    public string Username;
            
    [XmlAttribute("password")]    
    public string Password;
}
    
 public class UsernameClientAssertion: SecurityPolicyAssertion
{        
    private UserCredential credential;
           
    public UsernameClientAssertion()
    {
     }

Метод ReadXml считывает из файла параметры политики, состоящие из имени файла с именем пользователя и паролем. Хранение паролей в файле должно как минимум сочетаться с защитой данного файла средствами операционной системы. Однако задание пароля в программном коде (например, после ввода его пользователем с клавиатуры) невозможно при использовании веб службы любой не интерактивной программной компонентой.

public override void ReadXml(XmlReader reader,
    IDictionary<string, Type> extensions)
{
    string fileName = reader.GetAttribute("file");
    if (fileName == null)
        throw new Exception("Attribute 'file' not found in policy");
    
    // Обязательная операция - переход к следующему тегу в файле политики
    reader.Read();
             
    using (StreamReader stream = new StreamReader(fileName))
    {
        XmlSerializer serializer = new
            XmlSerializer(typeof(UserCredential));
        using (XmlTextReader xmlReader = new XmlTextReader(stream))
        {
           credential = (UserCredential) serializer.Deserialize(xmlReader);
        }    
    }
}