0

本题涉及的软件有:

  • SQL Server 报告服务 2008 R2
  • SQL Server 分析服务 2008 R2
  • SQL Server 2008 R2 数据库引擎
  • ASP.NET 4.5 Web 窗体
  • 报表查看器组件

我们有几十份报告。一些报表对我们的数据仓库数据库使用 T-SQL 查询,而一些报表对我们的 SSAS 多维数据集使用 MDX 查询。

Active Directory 安全组保护用户可以在报告服务器上访问的报告。

我们还制作了具有维度权限的 SSAS 角色,从而有效地保护了每个用户可以访问的数据。由于有多少,我们使用 AMO 代码来生成和维护这些角色和成员资格,但这无关紧要,与问题无关。

我知道 SSAS 有一个名为 EffectiveUserName 的功能,我们可以将其传递给多维数据集进行模拟。

但是,我们如何在 SSRS 中模拟用户,以便我们只能看到该用户有权访问的报告?

我们目前正在尝试使用 ASP.NET 并使用 ReportViewer 组件来设计自定义报表管理器的软件设计。我们希望向管理员公开一个文本框或下拉菜单,允许他们输入或选择员工并以该员工的身份有效运行。

换句话说,即使我以 DOMAIN\User1 身份在 ASP.NET 报表管理器站点中进行了身份验证,但如果我在报表服务器上担任管理员的某个角色,我希望能够在文本框中输入用户名像 User2 并且能够查看报表服务器上的所有报表,因为 DOMAIN\User2 会看到它们。

感谢您提供的任何建议或答案。

4

2 回答 2

1

一些东西:

  1. 根据我的经验,您需要在代码中执行此操作。
  2. 您需要一个“ReportViewer”对象。
  3. 我相信,如果您要托管,则需要参考“Microsoft.ReportViewer.WinForms”dll。

我使用的代码是使用用于托管 ReportViewer 的 WPF 的 xaml 完成的(删节):

< Window x:Class="WPFTester.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:rv="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"
    >
  ......
<WindowsFormsHost Grid.Row="2">
        <rv:ReportViewer x:Name="reportViewer"></rv:ReportViewer>
    </WindowsFormsHost>
......
</Window>

你得到的重要部分是我有一个名为“reportViewer”的“ReportViewer”对象,用于我的代码。ASP.NET 有这个对象的一些等价物,但您还需要 'rv' 或类似别名中的 dll。代码的工作方式与此类似:

private void ResetReportViewer(ProcessingMode mode)
        {
            this.reportViewer.Clear();
            this.reportViewer.LocalReport.DataSources.Clear();
            this.reportViewer.ProcessingMode = mode;
        }


        private void ReportViewerRemoteWithCred_Load(object sender, EventArgs e)
        {
            ResetReportViewer(ProcessingMode.Remote);
            reportViewer.ServerReport.ReportServerUrl = new Uri(@"(http://myservername/ReportServer");
            reportViewer.ServerReport.ReportPath = "/Test/ComboTest";

            DataSourceCredentials dsCrendtials = new DataSourceCredentials();
            dsCrendtials.Name = "DataSource1";  // default is this you may have different name
            dsCrendtials.UserId = "MyUser";  // Set this to be a textbox
            dsCrendtials.Password = "MyPassword";  // Set this to be a textbox
            reportViewer.ServerReport.SetDataSourceCredentials(new DataSourceCredentials[] { dsCrendtials });

            reportViewer.RefreshReport();
        }
于 2013-09-12T20:12:41.737 回答
-1

我从未使用过您提到的服务,但我希望以下内容能以某种方式帮助您。

我使用 kernal32.dll 和 advapi32.dll 来模拟用户,如下所示:

Imports System.Security.Principal
Imports System.Runtime.InteropServices

Public Class UserImpersonation
<DllImport("advapi32.dll")> _
Public Shared Function LogonUserA(ByVal lpszUserName As [String], ByVal lpszDomain As [String], ByVal lpszPassword As [String], ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer
End Function

<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function DuplicateToken(ByVal hToken As IntPtr, ByVal impersonationLevel As Integer, ByRef hNewToken As IntPtr) As Integer
End Function

<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function RevertToSelf() As Boolean
End Function

<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean
End Function

Public Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Public Const LOGON32_PROVIDER_DEFAULT As Integer = 0

Private impersonationContext As WindowsImpersonationContext

Private Const UserName As String = "USER_ID"
Private Const Password As String = "USER_DOMAIN_PASSWORD"
Private Const Domain As String = "USER_DOMAIN_NAME"

Public Function ImpersonateValidUser() As Boolean
    Dim tempWindowsIdentity As WindowsIdentity
    Dim token As IntPtr = IntPtr.Zero
    Dim tokenDuplicate As IntPtr = IntPtr.Zero
    If RevertToSelf() Then
        If LogonUserA(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
            If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                impersonationContext = tempWindowsIdentity.Impersonate()
                If impersonationContext IsNot Nothing Then
                    CloseHandle(token)
                    CloseHandle(tokenDuplicate)
                    Return True
                End If
            End If
        End If
    End If
    If token <> IntPtr.Zero Then
        CloseHandle(token)
    End If
    If tokenDuplicate <> IntPtr.Zero Then
        CloseHandle(tokenDuplicate)
    End If
    Return False
End Function

Public Sub UndoImpersonation()
    If impersonationContext IsNot Nothing Then
        impersonationContext.Undo()
    End If
End Sub

End Class

现在,在代码中的适当位置使用它,例如:

Public SomeOtherClass
Public Function ReadFile() As CalFileInfo
    Try
        Dim objImpersonation As New UserImpersonation()
        If (objImpersonation.ImpersonateValidUser()) Then
            'Do necessary stuff....
            objImpersonation.UndoImpersonation()
        Else
            objImpersonation.UndoImpersonation()
            Throw New Exception("User do not has enough permissions to perform the task")
        End If
    Catch ex As Exception
        ''MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    End Try

    Return CalFileInformation
End Function
End Class
于 2013-09-12T19:55:36.167 回答