SSRS报告多个公司/团队

时间:2014-05-28 07:42:14

标签: database-design reporting-services

我想要一些关于最佳实践的建议。

我正在维护SSRS报告服务器,现在需要支持多家公司。每家公司都应该只看到自己的数据。母公司应该能够看到所有数据,但也能够由子公司分开。

有些报告是相同的,只是查看整体数据的不同子集。

实现这一目标的最佳方法是什么,确保数据只能由相应的公司访问,以及我可以轻松更新报告等,以及稍后添加新公司?

我目前正在建设"核心"报告,然后使用带有公司名称的链接报告作为隐藏的默认参数。

或者,我考虑使用主数据的过滤视图为每个公司创建单独的数据库。那么我将改变源代码而不是参数。

我意识到这是一个悬而未决的问题,但想要了解更多有经验的人的利弊,然后才开始这样做。

2 个答案:

答案 0 :(得分:2)

有几种方法可以解决这个问题:

  • 合并数据库并按公司选择
  • 一个数据库中的模式,用于分隔公司。需要进行一些维护。
  • 每家公司分开数据库。跨公司的汇总可能很复杂。

假设这对于可以访问组合数据库的内部人员来说不是安全问题,最简单的是组合数据库,并且报告中包含逻辑,以确保人们只能看到他们被允许的公司。

这里有两个问题:

  1. 确定谁在运行报告
  2. 确定哪些公司可以运行报告
  3. Reporting Services使用@UserId全局变量为您解决了第一个问题。

    我假设你有一张表Company看起来像这样:

    CompanyId | Name        | ParentCompanyId
    ----------+-------------+----------------
    1         | ABC Inc.    | 
    2         | DEF Co.     | 1
    3         | GHI Ltd.    | 1
    4         | XYZ Corp.   | 
    

    我们需要一种将其映射到他们可以运行报告的公司的方法,因此我们创建了一个包含UserIdCompanyId字段的表格,以便将用户映射到他们的公司。

    UserId    | Name        | CompanyId
    ----------+-------------+----------
    10        | Alyssa      | 1
    20        | David       | 2
    30        | Gloria      | 3
    40        | Xavier      | 4
    

    所以Alyssa可以看到ABC公司和子公司DEF Co和GHI Ltd,而大卫只能看到DEF Co,Gloria只能看到GHI有限公司和Xavier只能看到XYZ公司。

    在报告中,您可以根据关系选择数据:

    SELECT Invoices.CompanyId, Invoices.Number, Invoices.Date, Invoices.Amount
    FROM Invoices
    INNER JOIN Companies ON Invoices.CompanyId = Companies.CompanyId
    INNER JOIN Users ON Users.UserId = @UserId 
                    AND ((Companies.CompanyId = Users.CompanyId) OR (Companies.ParentCompanyId = Users.CompanyId))
    

    好的,这需要确保用户只能看到与用户关联的公司和子公司的数据:David只能查看DEF Co的发票,而Alyssa会查看ABC Inc,DEF的所有发票Co和GHI有限公司

    现在,如果Alyssa只想看DEF Co,她需要能够选择那家公司。根据此查询创建@CompanyId参数:

    SELECT Companies.CompanyId, Companies.Name
    FROM Companies 
    INNER JOIN Users ON Users.UserId = @UserId 
                    AND ((Companies.CompanyId = Users.CompanyId) OR (Companies.ParentCompanyId = Users.CompanyId))
    

    这显示了用户可以选择的所有公司。设置参数的默认值以从查询中获取其值:

    SELECT CompanyId FROM Users WHERE UserId = @UserId
    

    然后我们将此参数添加到我们的查询中:

    SELECT Invoices.CompanyId, Invoices.Number, Invoices.Date, Invoices.Amount
    FROM Invoices
    INNER JOIN Companies ON Invoices.CompanyId = Companies.CompanyId
    INNER JOIN Users ON Users.UserId = @UserId 
                    AND ((Users.CompanyId = Companies.CompanyId) OR (Users.CompanyId = Companies.ParentCompanyId))
                    AND ((@CompanyId = Companies.CompanyId) OR (@CompanyId = Companies.ParentCompanyId))
    

    报告订阅

    现在我们开始通过订阅提交报告,我们围绕使用@UserId的策略分崩离析,因为报告调度程序在自己的帐户下运行报告,而不是我们想要定位的用户。

    让我们创建一个名为User的隐藏参数,并将其作为第一个参数。对于其“可用值”属性,请创建如下所示的查询:

    SELECT UserId, Name
    FROM Users
    WHERE UserId = @UserId OR @UserId = 'MyDomain\ReportingAccount'
    

    其中MyDomain\ReportingAccount是您的报告在其下运行的帐户。此查询仅在实际用户运行报表时允许特定用户详细信息,但在报表调度程序运行时允许所有用户。

    User参数的默认值属性设为=User!UserId。报表计划程序运行报表时,User参数会为您要发送电子邮件的人提供所需的UserId。

    因此,当用户运行报告时,它会选择唯一可能的用户(这是他们自己),并且当调度程序运行报告时,它会从所有可用用户中选择所需的用户。作为隐藏参数,用户永远不会看到它,因此不知道其中的差异。

    如果用户试图通过将其作为参数传递给URL来智能并欺骗其他用户,则它将不是参数可用值的有效选择,因此将失败。

    现在只需将上面用于公司选择的查询中的@UserId替换为@User,一切都应该有效。

答案 1 :(得分:0)

我会将安全实现向上推送到数据库,并强制通过筛选视图进行访问。通常的技术是构建一个表,列出每个用户可访问的公司,然后使用CURRENT_USER函数过滤具有该表的内部联接的视图。

这是一个更强大的解决方案,因为它不依赖于单个报告参数设置。它还将支持更多的部署方法,例如SharePoint,Web Apps,Excel等。

有了这个,您的Report Manager部署变得非常简单 - 您可以为所有用户提供对一组文件夹和报告的相同访问权限。