Разрешения сокетов
179C# и .NET --- Сетевое программирование --- Разрешения сокетов
Среда .NET Framework, предоставляет многочисленные классы, помогающие разрабатывать в приложениях безопасный код. Многие из этих классов предлагают основанную на ролях безопасность и криптографию. Среда .NET Framework также дает объекты разрешений доступа к коду, являющиеся компоновочными блоками для защиты от несанкционированного доступа к коду. Они являются фундаментом, гарантирующим управляемому коду безопасность — может выполняться только тот код, который имеет разрешение выполняться в текущем контексте.
Каждое разрешение доступа к коду демонстрирует одно из следующих прав:
Право доступа к защищенным ресурсам, например к файлам.
Право выполнения защищенной операции, например обращения к управляемому коду.
Для мира Интернета и особенно для сетевых приложений классы System.Net предоставляют встроенную поддержку аутентификации и разрешений доступа к коду. Среда .NET Framework дает класс SocketPermission, обеспечивающий соблюдение разрешений доступа к коду.
Класс SocketPermission используется для управления правами на установление и принятие соединений, контролирующими доступ к сети через сокеты. Этот класс состоит из спецификации хоста и набора "действий", определяющих способы установления соединений с этим хостом. Он обеспечивает безопасность кода, контролируя значения имени хоста, IP-адреса и транспортного протокола.
Для сокетов C# имеется два способа обеспечить разрешение, поддерживающее безопасность:
Императивно, используя класс SocketPermission
Декларативно, используя класс SocketPermissionAttribute
Синтаксис императивной безопасности реализует разрешения, создавая новый экземпляр класса SocketPermission, чтобы при выполнении кода запросить конкретное разрешение, например право установить TCP-соединение. Этот способ обычно применяется, когда настройки безопасности изменяются при выполнении приложения. В декларативном синтаксисе используются атрибуты, позволяющие поместить информацию о безопасности в метаданные нашего кода, чтобы клиент, вызывающий код, мог воспользоваться рефлексией и узнать, какие разрешения требуются для кода.
Императивная безопасность
Этот синтаксис для обеспечения безопасности создает новый экземпляр класса SocketPermission. Синтаксис императивной безопасности можно использовать для выполнения требований и переопределений, но не запросов. Прежде чем вызвать соответствующий критерий безопасности, необходимо через конструктор инициализировать состояние класса SocketPermission, чтобы он представлял конкретную форму разрешения, которую вы ищете.
В следующем приложении демонстрируется основное использование класса SocketPermission. Поскольку этот код ведет себя как клиент, до выполнения этой программы нужно запустить приложение SocketServer.cs, созданное ранее:
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Security.Permissions;
namespace SocketPermissionSample
{
class Program
{
static void Main(string[] args)
{
// Устанавливаем удаленную точку для сокета
IPHostEntry ipHost = Dns.GetHostEntry("localhost");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
Socket sender = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Настройка разрешений
SocketPermission permisSocket = new SocketPermission(
NetworkAccess.Connect, TransportType.Tcp, "localhost",
SocketPermission.AllPorts);
permisSocket.Assert();
try
{
// Соединяем сокет с удаленной endPoint, перехватываем все ошибки
sender.Connect(ipEndPoint);
Console.WriteLine("Сокет подключен к {0}", sender.RemoteEndPoint.ToString());
byte[] bytes = new byte[1024];
byte[] msg = Encoding.UTF8.GetBytes("Простой тест");
// Отправляем данные через сокет
int bytesSend = sender.Send(msg);
// Получаем ответ от удаленного устройства
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Текст ответа: {0}",
Encoding.UTF8.GetString(bytes, 0, bytesRec));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
if (sender.Connected)
{
// Освобождаем сокет
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}
Console.ReadLine();
}
}
}
Приведенный код показывает, как, используя императивный синтаксис, реализовать безопасность доступа к коду. Важность этого кода в данном случае заключается в вызове одного метода класса SocketPermission - Assert(), который указывает, что приложению разрешается давать согласие на запросы соединения от Интернета и местного ресурса.
Декларативная безопасность
Декларативная безопасность использует атрибуты .NET, чтобы поместить информацию о безопасности внутрь метаданных кода. Атрибуты можно поместить на уровне сборки, класса или члена и указать необходимый тип запроса, требования или переопределения. Для использования этого синтаксиса безопасности сначала через декларативный синтаксис нужно инициализировать данные состояния объекта SocketPermissionAttribute, чтобы он представлял форму разрешения, соблюдение которого обеспечивается в коде.
В следующем примере демонстрируется, как обеспечить выполнение разрешения с использованием SocketPermissionAttribute:
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Security.Permissions;
namespace SocketPermissionSample
{
class Program
{
static void Main(string[] args)
{
LegalMethod();
Console.ReadLine();
}
[SocketPermission(SecurityAction.Assert, Access="Connect",
Host="localhost", Port="All", Transport="Tcp")]
public static void LegalMethod()
{
Console.WriteLine("Legal Method");
// Устанавливаем удаленную точку для сокета
IPHostEntry ipHost = Dns.GetHostEntry("localhost");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
Socket sender = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// Соединяем сокет с удаленной endPoint
sender.Connect(ipEndPoint);
Console.WriteLine("Сокет подключен к {0}",
sender.RemoteEndPoint.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
if (sender.Connected)
{
// Освобождаем сокет
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}
}
}
}
По функциональности приведенная выше программа похожа на предыдущую, однако, в последней программе вместо императивной безопасности используется синтаксис декларативной безопасности, т.е. разрешения для сокета задаются в атрибуте SocketPermission.