You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular 6中为ngx-ssrs-reportviewer配置SSRS身份模拟?

我刚好处理过类似的Angular + .NET Core对接SSRS的场景,给你一套可行的身份模拟实现方案,分步骤来:

第一步:切换到后端代理模式,避免前端直接碰SSRS权限

之前你让Angular直接调用SSRS,导致必须给每个用户开服务器权限,还解决不了外网用户的问题。最稳妥的做法是让** .NET Core后端作为中间层**:前端只和你的后端交互,后端以有权限的身份去请求SSRS,再把报表内容返回给前端。这样所有权限逻辑都在后端控制,外网用户只要能访问你的后端就能看报表。

第二步:后端实现身份模拟的两种方式

根据你的用户场景(内网域用户/外网用户),选对应的方案:

方案A:Windows身份模拟(适合内网域环境)

如果你的用户大多是域内用户,或者你有一个专门的域账号有SSRS访问权限,可以在后端模拟这个账号去请求SSRS:

  1. 先在.NET Core项目里确保引用了System.Security.Principal.Windows相关依赖
  2. 写一个SSRS代理服务类,用Windows API实现身份模拟:
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;

public class SsrsProxyService
{
    // 调用Windows登录API
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool LogonUser(string username, string domain, string password,
        int logonType, int logonProvider, out IntPtr tokenHandle);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private extern static bool CloseHandle(IntPtr handle);

    public async Task<Stream> GetSsrsReport(string reportPath, Dictionary<string, string> parameters)
    {
        // 替换成你的有权限的域账号信息
        string domain = "你的域名称";
        string ssrsUser = "有权访问SSRS的账号";
        string ssrsPwd = "账号密码";

        IntPtr tokenHandle = IntPtr.Zero;
        try
        {
            // 登录并获取用户令牌
            bool isLoggedOn = LogonUser(ssrsUser, domain, ssrsPwd, 2, 0, out tokenHandle);
            if (!isLoggedOn)
                throw new Exception($"身份模拟失败,错误码:{Marshal.GetLastWin32Error()}");

            // 模拟该用户身份去请求SSRS
            using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(tokenHandle))
            {
                var client = new HttpClient();
                client.BaseAddress = new Uri("http://你的SSRS服务器地址/ReportServer/");
                
                // 构造报表渲染请求(这里以HTML格式为例,可改成PDF/Excel等)
                var queryParams = new Dictionary<string, string>
                {
                    {"rs:Command", "Render"},
                    {"rs:Format", "HTML4.0"},
                    {"rc:Toolbar", "true"},
                    {"Path", reportPath}
                };
                // 追加报表参数
                foreach (var param in parameters)
                    queryParams.Add(param.Key, param.Value);

                var queryString = new FormUrlEncodedContent(queryParams).ReadAsStringAsync().Result;
                var response = await client.GetAsync($"ReportExecution2005.asmx?op=Render&{queryString}");
                response.EnsureSuccessStatusCode();

                return await response.Content.ReadAsStreamAsync();
            }
        }
        finally
        {
            // 记得关闭令牌句柄
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
        }
    }
}
  1. 注意:这种方式要求后端服务器运行在Windows环境,且服务器进程有模拟用户的权限。

方案B:用SSRS服务账号统一访问(适合外网/非域场景)

如果有外网用户,或者没有域环境,直接创建一个专门的SSRS服务账号,给它开通所有需要访问的报表权限,后端用这个账号去请求SSRS即可:

  1. 在SSRS中创建本地账号或SQL账号,赋予报表的浏览权限
  2. 后端代码更简单,直接用账号凭证请求SSRS:
using System.Net.Http;
using System.Net;
using System.Collections.Generic;
using System.Threading.Tasks;

public class SsrsProxyService
{
    public async Task<Stream> GetSsrsReport(string reportPath, Dictionary<string, string> parameters)
    {
        // 配置SSRS服务账号凭证
        var handler = new HttpClientHandler
        {
            Credentials = new NetworkCredential("SSRS服务账号", "密码", "域名或本地机器名")
        };

        using (var client = new HttpClient(handler))
        {
            client.BaseAddress = new Uri("http://你的SSRS服务器地址/ReportServer/");
            
            var queryParams = new Dictionary<string, string>
            {
                {"rs:Command", "Render"},
                {"rs:Format", "HTML4.0"},
                {"rc:Toolbar", "true"},
                {"Path", reportPath}
            };
            foreach (var param in parameters)
                queryParams.Add(param.Key, param.Value);

            var queryString = new FormUrlEncodedContent(queryParams).ReadAsStringAsync().Result;
            var response = await client.GetAsync($"ReportExecution2005.asmx?op=Render&{queryString}");
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStreamAsync();
        }
    }
}

这种方式不需要模拟用户,统一用服务账号访问,更适合外网场景。

第三步:调整Angular前端,对接后端接口

之前用的ngx-ssrs-reportviewer可以调整一下,两种方式选其一:

方式1:直接渲染后端返回的报表HTML

在Angular组件里调用后端接口,拿到报表HTML后直接渲染:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  template: '<div [innerHTML]="reportContent"></div>'
})
export class ReportViewerComponent {
  reportContent: string | null = null;

  constructor(private http: HttpClient) {
    this.loadReport();
  }

  private loadReport() {
    const requestBody = {
      reportPath: "/你的报表文件夹/报表名称",
      parameters: { "参数1": "值1", "参数2": "值2" }
    };

    this.http.post('/api/ssrs/get-report', requestBody, { responseType: 'text' })
      .subscribe({
        next: (html) => this.reportContent = html,
        error: (err) => console.error('加载报表失败', err)
      });
  }
}

方式2:修改ngx-ssrs-reportviewer的数据源

如果想保留viewer的工具栏和交互功能,可以把viewer的reportServerUrl设置为你的后端接口地址,让后端转发所有viewer的请求到SSRS。不过这种方式需要后端处理更多SSRS的API请求(比如参数提交、报表刷新等),相对复杂一点,适合需要完整viewer交互的场景。

第四步:安全注意事项
  • 绝对不要在前端暴露SSRS账号密码,所有权限逻辑都放在后端
  • 给后端的报表接口加身份验证(比如JWT),确保只有合法用户能访问
  • 账号密码不要硬编码,用.NET Core的配置系统(比如appsettings.json配合加密,或者密钥管理服务)
  • 如果用Windows身份模拟,要确保后端服务器的进程有足够权限进行用户模拟

内容的提问来源于stack exchange,提问作者Maroof Raini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:13:49