суббота, 9 апреля 2011 г.

Настройка Forms авторизации в SQL Server Report Services


Введение
Понадобилось мне недавно настроить Forms авторизацию для Report Services MS SQL Server 2008 R2(SSRS). Спросив у Гугла, что он думает по этому поводу, нашел, что Forms авторизация вполне себе поддерживается в SSRS, однако для этого необходимо сконфигурировать сервер и создать Membership provider. Ребята из Microsoft любезно предоставляют пример провайдера в своих samples for SQL Server 2008 R2, так же, в MSDN есть статья о настройке сервера для работы с кастомными способами авторизации, что так же очень любезно со стороны корпорации. Но не все так просто! В Сети нашлось несколько вариантов настройки, но далеко не все они давали нужный результат и мне пришлось здорово помучиться и потратить кучу времени на то, что б разобраться. Сперва дам Вам ссылку на скачивание сэмплов и на статью в MSDN:
- http://msftrsprodsamples.codeplex.com/releases/view/45918 - samples;
- http://msdn.microsoft.com/en-us/library/ms160724(v=SQL.100).aspx – статья по настройке.
Итак, пока у нас загружаются файлы, давайте поговорим немного о том, как происходит авторизация в SSRS.



Немного теории
Немного покопавшись в Сети, все в том же MSDN можно найти статью с описанием того, как же работает аутентификация пользователя в SSRS - http://msdn.microsoft.com/en-us/library/aa902691(SQL.80).aspx. Надо сразу сказать, что эта форма аутентификации не работает в версиях Express и Express with Tools. После того, как часть расстроенных пользователей пошла на сайт Microsoft смотреть сколько стоит SQL Server 2008 R2, мы с Вами примемся за изучение механизма аутентификации.  Для начала определимся что же это за зверь такой – аутентификация?! 
Аутентификация – если верить Википедии, то это проверка принадлежности субъекту доступа предъявленного им идентификатора; подтверждение подлинности. Что это значит? В большинстве своем то, что где-то есть сайт или программа, в которой(м) есть страничка, вкладка или какой-либо другой объект, содержащий 2 поля для ввода логина и пароля и кнопки «Вход». Пользователь вводит туда свои регистрационные данные, нажимает кнопку и программа(пусть это будет именно программа) передает эти данные в метод, который, к примеру, обращается к базе данных с логинами и паролями пользователей, выбирает записи с указанным логином, а затем проверяет на совпадение пароль. Далее, в зависимости от результата: пользователь с таким логином найден и пароль правильный, не правильный пароль или пользователь с таким логином вообще никогда не существовал на этом сервере, метод возвращает true или false. А уже программа, на основе того, что вернул метод, понимает пускать пользователя дальше или пусть ограничится тем, что у него уже есть. Вот примерно так работает «сферическая Forms аутентификация в вакууме». Теперь, вооружившись новыми знаниями(для кого они будут новые), взглянем более пристально на аутентификацию в SSRS.  Для затравки – картинка!



Рис. 1. Так происходит аутентификация пользователя


Что мы видим? Прежде всего, после ввода логина и пароля, необходимо соединиться с Web-службой Report server'а и передать ей введенные пользователем данные. Далее, служба соединяется с membership provider’ом и передает ему пользовательские данные, провайдер идет в базу и валидует эти данные, а затем, возвращает true или false, в зависимости от результата проверки. Если проверка прошла успешно, то служба выдает клиенту Authentication ticket, благодаря которому, SSRS может понять, что правильный пользователь хочет получить доступ к непубличным данным. Для реализации Forms аутентификации, необходимо написать свой модуль Security Extension для Reporting Services и подключить его соответствующим образом. Модуль должен реализовывать интерфейс IAuthenticationExtension через перегрузку нескольких методов. Однако, хорошие парни из Microsoft облегчили нам задачу и предоставили свой тестовый модуль, который вы сможете найти установив скаченные (они уже скачались?!) примеры. Так, с аутентификацией разобрались и теперь мы знаем, что произойдет, когда мы нажмем кнопку «Login» в созданном и настроенном нами membership provider'е. Давайте теперь разбираться как происходит авторизация, да и что это вообще такое!
Для авторизации Википедия дает целых 3 определения:
1. Процесс предоставления определенному лицу прав на выполнение некоторых действий.
2. Процесс подтверждения (проверки) прав пользователей на выполнение некоторых действий. 
3. Проверка прав пользователя на осуществление транзакций, проводимая в точке обслуживания, результатом которой будет разрешение или запрет операций клиента (например, совершения акта купли-продажи, получения наличных, доступ к ресурсам или службам).
В нашем случае, авторизация контролирует права на использования объектов Reporting Services пользователем, уже прошедшего в нем аутентификацию. Для отображения процесса авторизации так же приведу картинку.
    


Рис. 2. Вся подноготная авторизации.


Пользователь, по уже выданному ему authentication ticket обращается к службе, которая, в свою очередь, обращается к Security extension модулю для проверки прав на доступ к запрашиваемому объекту. Модуль проверяет, можно ли доверить этому пользователю столь ценную информацию и, если решает все-таки доверить, сообщает службе о том, что данную информацию этому пользователю доверить можно, а служба уже в свою очередь предоставляет доступ к этой информации. Для реализации модуля авторизации необходимо реализовать интерфейс IAuthorizationExtension с перегрузкой методов CheckAccess, GetUserInfo и др. 
В результате работа Report server выглядит вот так:



Рис. 3. Общая схема работы Report server'а.


Не буду Вас утомлять описанием еще и этой картинки, а перейдем сразу к практике.


Наконец-то практика!
Вы уже установили скаченные примеры? Нет? Ну тогда мы немного подождем! Установили? Ура, поздравляю! Теперь заходите туда, куда установили эти примеры. По-умолчанию они устанавливаются в C:\Program Files\Microsoft SQL Server\100\Samples. Переходите в Reporting Services\ Extension Samples\FormsAuthentication Sample. Это и есть тот самый membership provider, придоставляемый в качестве примера. Извините, я Вас немного обманул! Прежде чем запускать Visual Studio и смотреть на код, нам надо настроить права пользователя и сгенерировать strong name key file.
Настройка прав пользователя
Прежде всего необходимо добавить учетную запись Guest в группу IIS_IUSRS. Затем нужно разрешить пользователю Guest доступ к папкам Report Server и Report Manager. Они находятся по-умолчанию в C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\. 
Генерация strong name key file
Для генерации ключа запустите командную строку Visual Studio (она находится в Start -> Microsoft Visual Studio <your VS version> -> Visual Studio Tools -> Visual Studio <your VS version> Command Prompt), перейдите, с помощью команды cd, в каталог с примерами (по-умолчанию C:\Program Files\Microsoft SQL Server\90\Samples) и наберите команду sn –k SampleKey.snk. После этого, у вас в каталоге с примерами появится файл с ключами – SampleKey.snk. Он нужен для подписи dll файлом secrity extension модуля. Вот теперь мы можем загрузить проект и посмотреть на код!
Смотрим код и компилируем его
Перейдите в папку с примерами, далее идите в Reporting Services\Extension Samples\FormsAuthentication Sample и вы увидите 2 папки, а так же HTML файл. В HTML файле описывается как подключить srcurity extension модуль к report service, в папках же хранятся проекты, написанные на C# (папка cs) и Visual Basic (папка, соответственно, vb). Выбирайте какой язык Вам ближе. Я же приведу описание проекта на C#, хотя разница с VB заключается лишь в синтаксисе языка. Итак, загружаем проект и видим, что у нас есть 2 ASPX странички и несколько классов 



Рис. 4. Структура security extension модуля.


Во-первых, необходимо проверить подключена ли библиотека Microsoft.ReportingServices.Interfaces.



Рис. 5. Подключенная библиотека Microsoft.ReportingServices.Interfaces.


Если ее нет в списке, то вы можете подключить ее сами. Она находится в папке Report server\bin (полный путь по-умолчанию - C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin). Далее осмотритесь в проекте – там  все довольно просто и понятно, так что не буду описывать. Сразу дам совет – вынесите connection strings в константу, а еще лучше – в конфигурационный файл. Так же можете добавить логирование событий по своему вкусу. Затем компилируйте проект и, если все прошло гладко – закрывайте студию. 


Копирование файлов
Теперь нам надо скопировать созданные dll и pdb (если вы хотите иметь возможность отлаживать модуль) файлы, а так же Logon.aspx и UILogon.aspx. Dll и pdb надо положить в папки bin для Report Server и Report Manager, а Logon.aspx – в папку Report Server и UILogon.aspx – в папку Report Manager\Pages.


Правим конфиги
Ну, вот и пришел черед править конфиги. Они находятся в папках сервера и менеджера. Перво-наперво, сделайте бэкап существующих конфигов – они вам очень понадобятся! Сперва правим конфиги сервера. Они находятся в директории <install>\Report Server(где <install> - путь к установленному SSRS).


RSReportServer.config
Находим элемент <Authentication> и заменяем его на указанный ниже
<Authentication>
<AuthenticationTypes>
<Custom/>
</AuthenticationTypes>
<EnableAuthPersistence>true</EnableAuthPersistence>
</Authentication>


Находим ниже элементы <Security> и  <Authentication>, внутри которых содержаться элементы <Extensions> и заменяем их на:
<Security>
   <Extension Name="Forms" 
Type="Microsoft.Samples.ReportingServices.CustomSecurity.Authorization, 
Microsoft.Samples.ReportingServices.CustomSecurity" >
      <Configuration>
         <AdminConfiguration>
            <UserName>username</UserName>
         </AdminConfiguration>
      </Configuration>
   </Extension>
</Security>
<Authentication>
   <Extension Name="Forms" 
Type="Microsoft.Samples.ReportingServices.CustomSecurity.AuthenticationExtension,
 Microsoft.Samples.ReportingServices.CustomSecurity" />
</Authentication>


Изменяем элемент <UI>
<UI>
   <CustomAuthenticationUI>
      <loginUrl>/Pages/UILogon.aspx</loginUrl>
         <UseSSL>True</UseSSL>
   </CustomAuthenticationUI>
   <ReportServerUrl>http://<server>/ReportServer</ReportServerUrl>
</UI>


RSSrvPolicy.config
Добавляем элемент <CodeGroup> перед элементом, в котором содержится атрибут $CodeGen в URL membership
<CodeGroup
   class="UnionCodeGroup"
   version="1"
   Name="SecurityExtensionCodeGroup"
   Description="Code group for the sample security extension"
   PermissionSetName="FullTrust">
   <IMembershipCondition 
      class="UrlMembershipCondition"
      version="1"
      Url="C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportServer\bin\Microsoft.Samples.ReportingServices.CustomSecurity.dll"
   />
</CodeGroup>


Web.config
Открываем его и изменяем в <identity> свойство Impersonate на false
<identity impersonate="false" />


Изменяем атрибут <authentication >
<authentication mode="Forms">
   <forms loginUrl="logon.aspx" name="sqlAuthCookie" timeout="60" 
               path="/"></forms>
   </authentication>


И добавляем ниже 
<authorization> 
   <deny users="?" />
</authorization>


Теперь примемся за конфиги Report Manager’а. Его файлы конфигурации находятся в папке <install>\Report Manager.
RSMgrPolicy.config
Находим среди элементов <CodeGroup> тот, у которого Zone="MyComputer" и изменяем ему свойство PermissionSetName с Execution  на FullTrust.
<CodeGroup 
        class="FirstMatchCodeGroup" 
        version="1" 
        PermissionSetName="FullTrust"
        Description="This code group grants MyComputer code Execution 
permission. ">
    <IMembershipCondition 
            class="ZoneMembershipCondition"
            version="1"
            Zone="MyComputer" />


Кстати, то же самое надо сделать и в policy-файле сервера!


Web.config 
Заменяем <identity impersonate= "true" /> на <identity impersonate="false" /> и добавляем в <appSettings> 2 элемента:
<add key="ReportServer" value="<Server Name>"/>
<add key="ReportServerInstance" value="<Instance Name>"/>


<Server Name> - это имя вашего SQL сервера, <Instance Name> можно узнать выполнив в PowerShell следующий командлет:
get-wmiobject -namespace “root\Microsoft\SqlServer\ReportServer” -class  “__Namespace”
Вот с конфигурацией и покончено. Теперь надо создать БД для хранения пользовательских данных.


Создаем базу данных
В папке с примером реализации провайдера для Forms Authorization есть папка Setup, в которой лежит файл CreateUserStore.sql. Это SQL-запрос, который создает таблицу для хранения пользовательских данных. Открываем этот файл в SQL Server Management Studio и выполняем его! Теперь на сервере появилась новая БД – User Accounts. 


Все! Теперь, если вы зайдете на http://<servername>/reportserver, то увидите окно с приглашением ввода логина и пароля. Вам необходимо сперва добавить этот узел в Trused Sites, что бы получать от сервера cookies. Когда вы логинитесь в сервере, вы получаете cookie, благодаря которым, вы можете залогиниться в менеджере(http://<servername>/reports).



Рис. 6. Форма авторизации в Report Server

P.S. от пользователя Владислав Швед:
Go to Databases-> UserAccounts->Security->Users Right Click Users select "New User" In General: Select "Windows User" under UserType dropdown. Enter "NT SERVICE\ReportServer" for Username. Enter "NT SERVICE\ReportServer" for Password. Enter "NT SERVICE\ReportServer" for Default Schema. In Membership: Check db_owner Access to NT Service\ReportServer to UserAccounts Database is given. иначе будут проблемы с пермишенами Configuration> <AdminConfiguration> <UserName>username</UserName> </AdminConfiguration> </Configuration> и вместо username должно быть имя, под которым логинимся.

2 комментария:

  1. Хорошая статья, но до конца дело не дошло.
    Теперь сервер не доступен по servername/reports
    просто пишет server unavailable.

    и как посмотреть инстанс сервера я не понял, т.е понял, но не понял что из тех параметров является инстансом "RS_MSSQLSERVER" ?

    ОтветитьУдалить
    Ответы
    1. Да, "RS_MSSQLSERVER" - это инстанс. Вообще, поле Name - это инстанс сервера, а _SERVER - это его имя.

      А насчет ошибки "server unavailable" - посмотрите в Event Log что туда сыпется, тогда и можно будет понять причину.

      Удалить