如何在Angular 6中为ngx-ssrs-reportviewer配置SSRS身份模拟?
我刚好处理过类似的Angular + .NET Core对接SSRS的场景,给你一套可行的身份模拟实现方案,分步骤来:
第一步:切换到后端代理模式,避免前端直接碰SSRS权限
之前你让Angular直接调用SSRS,导致必须给每个用户开服务器权限,还解决不了外网用户的问题。最稳妥的做法是让** .NET Core后端作为中间层**:前端只和你的后端交互,后端以有权限的身份去请求SSRS,再把报表内容返回给前端。这样所有权限逻辑都在后端控制,外网用户只要能访问你的后端就能看报表。
第二步:后端实现身份模拟的两种方式
根据你的用户场景(内网域用户/外网用户),选对应的方案:
方案A:Windows身份模拟(适合内网域环境)
如果你的用户大多是域内用户,或者你有一个专门的域账号有SSRS访问权限,可以在后端模拟这个账号去请求SSRS:
- 先在.NET Core项目里确保引用了
System.Security.Principal.Windows相关依赖 - 写一个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); } } }
- 注意:这种方式要求后端服务器运行在Windows环境,且服务器进程有模拟用户的权限。
方案B:用SSRS服务账号统一访问(适合外网/非域场景)
如果有外网用户,或者没有域环境,直接创建一个专门的SSRS服务账号,给它开通所有需要访问的报表权限,后端用这个账号去请求SSRS即可:
- 在SSRS中创建本地账号或SQL账号,赋予报表的浏览权限
- 后端代码更简单,直接用账号凭证请求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
相关产品推荐
相关产品推荐

