Как правильно настроить соединение с базой данных - PullRequest
7 голосов
/ 03 июня 2010

похожи, но не одинаковы:

Привет всем, у меня есть приложение C # WinForms, подключающееся к серверу базы данных. Строка подключения к базе данных, включая универсальный user / pass, помещается в файл конфигурации NHibernate, который находится в том же каталоге, что и exe-файл.

Теперь у меня есть проблема: пользователь, который запускает приложение, не должен знать имя пользователя / пароль обычного пользователя базы данных, потому что я не хочу, чтобы он копался в базе данных напрямую.

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

Пока я нашел три возможности:

  1. На первый указанный вопрос обычно отвечали , что делало файл доступным для чтения только пользователю, который запускает приложение .

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

  2. В первом ответе дополнительно предлагается зашифровать данные соединения перед записью их в файл .

    При таком подходе администратор больше не может настраивать строку подключения, поскольку он не может зашифровать ее вручную.

  3. Второй второй вопрос *1040* дает подход для этого самого сценария, но он кажется очень сложным.

Мои вопросы к вам:

  1. Это очень общая проблема, поэтому не существует общего способа "как это сделать", каким-то образом "шаблон проектирования"?

  2. Есть ли некоторая поддержка в конфигурационной инфраструктуре .NET?

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

Обновление:

В ответ на первые ответы: Есть несколько причин, по которым я бы хотел подключиться к базе данных напрямую и не использовать веб-сервис :

  • (N) Hibernate может использоваться только с базой данных, но не с веб-сервисами (я прав?)
  • Мы планируем предоставить возможность работы в автономном режиме, т. Е. Если база данных или сеть отключены, пользователь может продолжить свою работу. Чтобы справиться с этим, я думаю, что у меня есть локальная внутрипроцессная база данных, например, SQL Server Compact и использование инфраструктуры MS Sync для синхронизации его с базой данных сервера, как только он снова заработает.

Есть ли у вас какие-либо идеи с учетом этого?

Ответы [ 4 ]

5 голосов
/ 03 июня 2010

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

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

Что бы вы ни делали, вы не можете передать имя пользователя / пароль привилегированного пользователя ненадежному человеку. Это просто напрашивается на неприятности. Независимо от того, насколько хорошо вы пытаетесь скрыть свои учетные данные в зашифрованной строке внутри двоичного файла или еще чего-то, всегда есть способ их выяснить. Конечно, будет ли кто-то на самом деле делать это, зависит от того, насколько интересны ваши данные, но молча надеяться, что люди с отладчиками просто оставят вас в покое, не очень хорошая мера безопасности.

3 голосов
/ 04 июня 2010

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

Практически только один пользователь для базы данных, тот, который использует WebService, и если вы хотите, чтобы пользователь приложения имел разные привилегии db, вы абстрагируете его от уровня WebService

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

Для автономной работы все сводится к созданию безопасного способа сохранения ваших данных в локальном хранилище и предоставлению метода синхронизации через WebService

Я фактически сделал это, используя веб-сервис, который обменивался данными с БД, и приложение WinForm (.NET Compact Framework), которое общалось только с веб-сервисом, и в случае отсутствия покрытия сотовой сети оно сериализовало бы изменения на карте памяти ( данные не были важны, поэтому для моего случая неясные / непристойные меры безопасности, если они не были приняты)

ОБНОВЛЕНИЕ с небольшим примером в соответствии с просьбой (я нахожу странным, хотя просить пример по этому вопросу)

вы настроили ваши доменные классы и конфигурацию nhibernate и (например) ваш репозиторий в проекте типа ASP.NET WebService Application. Для простоты у меня будет только один класс веб-сервиса Foo (в Foo.asmx.cs) и один Bar класс домена

так что вы получите это (фактическая реализация варьируется):

namespace FWS
{
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class FooService : WebService
    {
        private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender");
        private readonly IDaoFactory daoFactory = new DaoFactory();
        private readonly ISession nhSession =  HibernateSessionManager.Instance.GetSession();
    }

    [WebMethod]
    public Bar[] GetFavoriteBars(string someParam, int? onceMore){
        return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[]
    }
}

и мы абстрагируем daobehaviour или просто используем nhsession напрямую, представленный в виде веб-метода.

Теперь из приложения WinForm все, что вам нужно сделать, это Add a WebReference, который вносит все необходимые изменения в конфигурацию, но также генерирует все необходимые классы (в этом примере он создаст класс Bar, поскольку веб-служба предоставляет его ).

namespace WinFormK
{
    public class KForm(): System.Windows.Forms.Form
    {
        public void Do()
        {
            var service = new FWS.FooService();
            string filePath = "C:\\temp\FooData.xml";
            Bar[] fetched = service.GetFavoriteBars("yes!", null);

            //lets write this to local storage
            var frosties = new XmlSerializer(typeof(Bar));
            TextReader reader = new StreamReader(filePath);

            try
            {
                var persisted = (T)frosties.Deserialize(reader);
            }
            catch(InvalidOperationException)
            {
                //spock, do something
            }
            finally
            {
                reader.Close();
                reader.Dispose();
            }
        }
    }
}

Есть некоторые вещи, на которые вы должны обратить внимание:

  • По сути, вы теряете ленивые вещи или, по крайней мере, теряете их в своем приложении winform. Сериализатор XML не может сериализовать прокси-серверы, поэтому вы либо лениво выбираете эти коллекции / свойства, либо используете атрибут [XmlIgnore], который, в свою очередь, делает то, что подразумевается при сериализации.
  • Невозможно вернуть интерфейсы для подписей WebMethod. Они должны быть конкретными классами. Таким образом, возвращение IList<Bar> должно быть преобразовано в List<Bar> или что-то вроде
  • Веб-служба выполняется IIS и отображается в веб-браузере. По умолчанию будут обрабатываться только запросы локального браузера (но это можно изменить), поэтому вы можете протестировать слой доступа к данным отдельно от того, что делает ваша winform.
  • Принимающая сторона (приложение winform) ничего не знает о NHibernate.
  • В приведенном выше примере я сохранил то же имя для dao-методов для веб-методов; Пока вы не сохранили специфичные для nhibernate методы в вашем дао (скажем, как параметр NHibernate.Criterions.Order), вы, вероятно, не найдете никаких проблем. На самом деле вы можете иметь столько .asmx классов в своем веб-сервисе, сколько захотите, возможно, даже «сопоставить» их с соответствующими дао (например, public class FooService : WebService, public class BarService : WebService, public class CheService : WebService, где каждый соответствует DAO).
  • Вам, вероятно, придется написать какой-то метод опроса между конечными точками, чтобы сохранить представленные данные свежими.
  • Данные WebService являются подробными; чрезвычайно так. Рекомендуется заархивировать их или что-то еще перед отправкой по проводам (и, возможно, также зашифровать их)
  • приложение win знает только запись конфигурации: http://server/FWS/FooService.asmx
  • По умолчанию на веб-сервисах сессия отключена. помните, что перед началом использования сеанса для пользовательских данных.
  • Вам, вероятно, придется написать какую-то аутентификацию для веб-сервиса
  • В приведенном выше примере я возвращаю Bar[] с Bar, сопоставленным с nhibernate. Чаще всего это может быть не так, и вам может потребоваться написать вспомогательный класс WSBar, в котором он адаптирует исходный класс Bar к тому, что может потреблять веб-служба и приложение winform. Этот класс на самом деле просто носитель данных. Опять же, это зависит от степени интеграции с классами вашего домена и nhibernate, а также от того, насколько сложны ваши классы: некоторые структуры данных не могут быть сериализованы по умолчанию.

  • Эта модель может не соответствовать тому, что вы уже сделали со своим приложением

1 голос
/ 03 июня 2010

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

1 голос
/ 03 июня 2010

Я думаю, что это трудно сделать: как будто вы не хотите, чтобы пользователь stackoverflow знал свой пароль. Пользователь всегда может отследить свой сетевой трафик и увидеть имя пользователя / пароль (у вас может быть кодировка, но я все равно не уверен на 100%).

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

...