Вопрос

Мне нужно написать веб-приложение с использованием SQL Server 2005, asp.net и ado.net.Большая часть пользовательских данных, хранящихся в этом приложении, должна быть зашифрована (читайте HIPAA).

Раньше для проектов, требующих шифрования, я шифровал/расшифровывал код приложения.Однако обычно это предназначалось для шифрования паролей или информации о кредитных картах, поэтому в нескольких таблицах было всего несколько столбцов.Для этого приложения необходимо зашифровать гораздо больше столбцов в нескольких таблицах, поэтому я подозреваю, что перенос функций шифрования на уровень данных будет более эффективным, особенно с учетом встроенной поддержки нескольких типов шифрования в SQL Server 2005.(Я мог бы убедиться в обратном, если бы у кого-нибудь были реальные эмпирические доказательства.)

Я консультировался с BOL и достаточно хорошо разбираюсь в Google.Поэтому мне не нужны ссылки на онлайн-статьи или документацию MSDN (вероятно, я ее уже читал).

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

Итак, однократные шаги настройки (теоретически выполняются администратором базы данных):

  1. Создать главный ключ
  2. Создайте резервную копию главного ключа в файле, запишите его на компакт-диск и храните вне офиса.
  3. Откройте главный ключ и создайте сертификат.
  4. Сделайте резервную копию сертификата в файл, запишите его на компакт-диск и храните отдельно.
  5. Создайте симметричный ключ с выбранным алгоритмом шифрования, используя сертификат.

Затем в любое время, когда хранимой процедуре (или пользователю-человеку через Management Studio) потребуется доступ к зашифрованным данным, вам необходимо сначала открыть симметричный ключ, выполнить любые инструкции или пакеты tsql, а затем закрыть симметричный ключ.

Тогда, что касается приложения asp.net и, в моем случае, уровня доступа к данным кода приложения, шифрование данных полностью прозрачно.

Итак, мои вопросы:

  1. Хочу ли я открыть, выполнить операторы/пакеты tsql, а затем закрыть симметричный ключ внутри процедуры?Опасность, которую я вижу, заключается в том, что если что-то пойдет не так с выполнением tsql, и выполнение кода spproc никогда не достигнет оператора, закрывающего ключ.Я предполагаю, что это означает, что ключ останется открытым до тех пор, пока sql не уничтожит SPID, на котором выполнялась процедура.

  2. Должен ли я вместо этого рассмотреть возможность выполнения трех вызовов базы данных для любой процедуры, которую мне нужно выполнить (только когда необходимо шифрование)?Один вызов базы данных для открытия ключа, второй вызов для выполнения процедуры и третий вызов для закрытия ключа.(Каждый вызов заключен в собственный цикл try-catch, чтобы максимизировать вероятность того, что открытый ключ в конечном итоге закроется.)

  3. Есть ли соображения, следует ли мне использовать транзакции на стороне клиента (то есть мой код является клиентом и инициирует транзакцию, выполняет несколько процедур, а затем фиксирует транзакцию, предполагая успех)?

Это было полезно?

Решение

1) Изучите возможность использования TRY..CATCH в SQL 2005.К сожалению, FINALLY не существует, поэтому вам придется обрабатывать как успешные, так и ошибочные случаи индивидуально.

2) Не требуется, если (1) занимается очисткой.

3) На самом деле нет разницы между клиентскими и серверными транзакциями с SQL Server.Connection.BeginTransaction() более или менее выполняет «BEGIN TRANSACTION» на сервере (и System.Transactions/TransactionScope делает то же самое, пока не будет повышен до распределенной транзакции).Что касается проблем с многократным открытием/закрытием ключа внутри транзакции, я не знаю никаких проблем, о которых следует знать.

Другие советы

Я большой сторонник варианта 3.

Представьте на минуту, что вы все равно собираетесь настроить инфраструктуру транзакций, где:

  1. Всякий раз, когда должен был быть сделан вызов к хранилищу данных, если существующая транзакция не была запущена, она создавалась.
  2. Если транзакция уже существует, вызовы хранилища данных перехватывают эту транзакцию.Это часто полезно для бизнес-правил, которые возникают в результате событий сохранения или перехода в базу данных.ИЕ.Если бы у вас было правило, согласно которому всякий раз, когда вы продаете виджет, вам необходимо обновить таблицу WidgetAudit, вы, вероятно, захотите обернуть вызов вставки аудита виджета в ту же транзакцию, что и та, которая сообщает хранилищу данных, что виджет был продан.
  3. Всякий раз, когда первоначальный вызывающий объект хранилища данных (начиная с шага 1) завершает работу, он фиксирует/откатывает транзакцию, что влияет на все действия с базой данных, произошедшие во время его вызова (с использованием try/catch/finally).

Как только этот тип транзакции создан, становится просто прикрепить открытый ключ в начале (когда транзакция открывается) и закрыть ключ в конце (непосредственно перед завершением транзакции).Выполнение «вызовов» хранилища данных не так затратно, как открытие соединения с базой данных.На самом деле такие вещи, как SQLConnection.Open(), сжигают ресурсы (даже если ADO.NET объединяет их за вас).

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

Всего 2 цента.Удачи.

  1. вы можете использовать @@error, чтобы узнать, возникли ли какие-либо ошибки во время вызова процедуры в SQL.

  2. Нет, сложному.

  3. Вы можете, но я предпочитаю использовать транзакции в самом SQL Server.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top