Как Вы дразните свои репозитории?

Это расширение ответа, связанного с Ezlo ( SQL Server EXECUTE AS проблема ), о котором я собираюсь рассказать Включение кросс-доступа к базе данных в SQL Server . [ 1114]

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

--Create a couple of sample databases
CREATE DATABASE SampleDB1;
CREATE DATABASE SampleDB2;
GO

USE SampleDB2;
GO
--Create a sample table
CREATE TABLE dbo.SampleTable (ID int, Somestring varchar(25));
GO
USE SampleDB1;
GO
--Create a sample SP and User/Login;
CREATE PROC dbo.SomeProc AS

    SELECT ID,
           SomeString
    FROM SampleDB2.dbo.SampleTable;
GO
CREATE LOGIN SampleCredential WITH PASSWORD = 'abc123', CHECK_EXPIRATION = OFF, CHECK_POLICY = OFF, DEFAULT_LANGUAGE = BRITISH;
CREATE USER SampleCredential FOR LOGIN SampleCredential;

GRANT EXEC ON dbo.SomeProc TO SampleCredential;
GO

--Test
EXECUTE AS LOGIN = 'SampleCredential';
GO
--This will fail
EXEC dbo.SomeProc;
GO
REVERT;
GO

Как вы можете видеть, если вы запустите этот скрипт, вы получите сообщение об ошибке: [ 1116]

Сообщение 916, Уровень 14, Состояние 1, Процедура SomeProc, Строка 4 [Стартовая Строка 28] Участник сервера "SampleCredential" не может получить доступ к базе данных "SampleDB2" в текущем контексте безопасности.

blockquote>

Итак, что такое кросс-доступ к базе данных? Процитируем из документации:

Создание цепочки владения несколькими базами данных происходит, когда процедура в одной базе данных зависит от объектов в другой базе данных. Цепочка владения несколькими базами данных работает так же, как цепочка владения в пределах одной базы данных, за исключением того, что непрерывная цепочка владения требует, чтобы все владельцы объектов были сопоставлены одной и той же учетной записи входа. Если исходный объект в исходной базе данных и целевые объекты в целевых базах данных принадлежат одной и той же учетной записи для входа в систему, SQL Server не проверяет разрешения для целевых объектов.

blockquote>

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

Цепочка владения по базам данных отключена по умолчанию. Microsoft рекомендует отключить цепочку владения несколькими базами данных, поскольку она подвергает вас следующим угрозам безопасности:

  • Владельцы базы данных и члены ролей базы данных db_ddladmin или db_owners могут создавать объекты, которыми владеют другими пользователями. Эти объекты могут потенциально предназначаться для объектов в других базах данных. Это означает, что если вы включаете цепочку владения несколькими базами данных, вы должны полностью доверять этим пользователям данные во всех базах данных.

  • Пользователи с разрешением CREATE DATABASE могут создавать новые базы данных и присоединять существующие базы данных. Если включена цепочка владения несколькими базами данных, эти пользователи могут получать доступ к объектам в других базах данных, к которым у них могут отсутствовать привилегии, из вновь созданных или присоединенных баз данных, которые они создают.

blockquote>

Хорошо, теперь, когда предостережение не в порядке, что с этим делать. Продолжая из приведенного выше сценария, нам нужно включить перекрестную цепочку владения БД на сервере, если это еще не сделано. Вы можете сделать это, выполнив следующее:

EXEC sp_configure 'show advanced', 1;
RECONFIGURE;  
GO
EXEC sp_configure 'cross db ownership chaining', 1;  
RECONFIGURE;  
GO
EXEC sp_configure 'show advanced', 0;
RECONFIGURE;  
GO

Теперь, когда это включено, вы можете включить DB_CHAINING в базах данных 2 :

ALTER DATABASE SampleDB1 SET DB_CHAINING ON;
ALTER DATABASE SampleDB2 SET DB_CHAINING ON;
GO

You ' Затем мне нужно будет создать пользователя для вашего логина в другой базе данных, но не нужно будет давать ему какие-либо разрешения, так что это будет «хорошо» (это не позволит им SELECT из таблицы за пределами SP):

USE SampleDB2;
GO
CREATE USER SampleCredential FOR LOGIN SampleCredential;
GO

Наконец, вы можете снова протестировать:

USE SampleDB1;
--Test
EXECUTE AS LOGIN = 'SampleCredential';
GO
--It works (0 rows returned)
EXEC dbo.SomeProc;
GO
REVERT;
GO

Если вы хотите дважды проверить, что пользователь не может выбрать из базы данных, вы можете сделать это :

USE SampelDB1;
GO
--This will fail
SELECT *
FROM SampleDB2.dbo.SampleTable;
GO

И, наконец, очистка (для хорошей меры):

--Cleanup
USE master;
DROP DATABASE SampleDB2;
DROP DATABASE SampleDB1;
DROP LOGIN SampleCredential;
EXEC sp_configure 'show advanced', 1;
RECONFIGURE;  
GO
EXEC sp_configure 'cross db ownership chaining', 0;  
RECONFIGURE;  
GO
EXEC sp_configure 'show advanced', 0;
RECONFIGURE;  
GO

8
задан Jim G. 4 October 2009 в 03:18
поделиться

3 ответа

Я обычно вижу два сценария с репозиториями. Я прошу что-то, и я получаю его, или я прошу что-то, и это не там.

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

Трудно кодированный тест удваивается, в порядке, если Вы делаете интеграционное тестирование. Скажите, Вы хотите сохранить объект и затем вернуть его. Но это тестирует взаимодействие двух объектов вместе, не только поведение SUT. Они - две разных вещи. Если Вы начинаете кодировать поддельные репозитории, Вам нужны модульные тесты на тех также, иначе Вы заканчиваете тем, что основывали успех и отказ Вашего кода непротестированного кода.

Это - мое мнение о Насмешке по сравнению с Тестом, Удваивается.

6
ответ дан 5 December 2019 в 14:07
поделиться

SCNR:

"Вы называете себя репозиторием? Я видел спичечные коробки с большей способностью!"

6
ответ дан 5 December 2019 в 14:07
поделиться

Я предполагаю, что "репозиторием" Вы имеете в виду ДАО; если не затем этот ответ не будет применяться.

В последнее время я делал "в памяти" "насмешку" (или тест) реализациями моего ДАО, которые в основном работают прочь данных (Список, Карта, и т.д.) передал в конструктора насмешки. Таким образом, класс модульного теста свободен добавить безотносительно данных, в которых он нуждается для теста, может изменить его, и т.д., не вынуждая все модульные тесты, воздействующие на "в памяти" ДАО быть кодированными для использования тех же данных тестирования.

Один плюс это я вижу в этом подходе, то, что, если у меня есть дюжина модульных тестов, которые должны применить тот же ДАО для их теста (для введения в класс под тестом, например), я не должен помнить все детали данных тестирования каждый раз (как Вы были бы, если "насмешка" была hardcoded) - модульный тест создает сами данные тестирования. На оборотной стороне это означает, что каждый модульный тест должен потратить, некоторые выстраивают в линию создание и проводное соединение, это - данные тестирования; но это - небольшая оборотная сторона мне.

Пример кода:

public interface UserDao {
    User getUser(int userid);
    User getUser(String login);
}

public class InMemoryUserDao implements UserDao {

    private List users;

    public InMemoryUserDao(List users) {
        this.users = users;
    }

    public User getUser(int userid) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (userid == user.getId()) {
                return user;
            }
        }

        return null;
    }

    public User getUser(String login) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (login.equals(user.getLogin())) {
                return user;
            }
        }

        return null;
    }
}
0
ответ дан 5 December 2019 в 14:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: