如何以Azure AD已认证用户身份在ASP.NET ReportViewer中执行SSRS报表
问题与解决方案:Azure认证用户访问本地SSRS报表
问题背景
我们的SQL Server Reporting Service(SSRS)部署在企业本地内网,仅允许域内计算机通过原生门户访问报表。目前正在开发一个基于ASP.NET Web Forms的报表包装应用,使用ReportViewer控件展示报表,托管于Azure App Service,采用Azure内置的Easy Auth实现SSO,身份提供商为Microsoft Active Directory。
当前通过硬编码域账号凭据访问SSRS的代码可正常运行,但只能使用一个拥有全报表权限的服务账号,无法实现用户级的权限控制。需求是:能否以Azure中已认证的当前用户身份访问SSRS,让每个用户仅能查看自己在SSRS原生门户被授权的报表?
可行方案与实现步骤
可以实现,核心是将Azure认证用户的身份传递到本地SSRS,结合AD信任、Kerberos约束委派或Azure AD Application Proxy完成身份映射与权限校验。
1. 建立Azure AD与本地AD的混合身份信任
- 确保Azure AD与本地企业AD通过Azure AD Connect完成用户同步,使Azure中认证的用户与本地域用户一一对应。
- 确认Azure App Service的Easy Auth已配置为使用同步后的Azure AD租户,用户登录后可获取完整的域用户身份信息(如
UserPrincipalName)。
2. 配置Kerberos约束委派(KCD)实现身份传递
这是本地SSRS与Azure App Service集成的标准身份传递方案:
- 在本地AD中,为Azure App Service对应的托管标识(或用于连接本地的服务账户)配置约束委派,允许其向SSRS服务(
HTTP/ssrs-server.domain.com)委派用户身份。 - 确保本地SSRS服务器已启用Kerberos认证(而非仅NTLM),可通过SSRS配置管理器或
rsconfig.exe完成设置。
3. 修改代码逻辑传递用户身份
不再使用硬编码凭据,而是基于当前Azure认证用户的域身份进行Kerberos身份模拟:
- 获取当前用户的域身份信息:
// 从Easy Auth的ClaimsPrincipal中提取用户UPN var userUpn = HttpContext.Current.User.Identity.Name; var domain = userUpn.Split('@')[1]; var username = userUpn.Split('@')[0]; // 转换为Windows身份对象 var userIdentity = new WindowsIdentity($"{domain}\\{username}"); - 调整自定义
CustomSSRSCredentials类适配Kerberos:public class CustomSSRSCredentials : IReportServerCredentials { private readonly WindowsIdentity _userIdentity; public CustomSSRSCredentials(WindowsIdentity userIdentity) { _userIdentity = userIdentity; } public WindowsIdentity ImpersonationUser => _userIdentity; public ICredentials NetworkCredentials => null; // Kerberos无需显式凭据 public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority) { authCookie = null; userName = password = authority = null; return false; } } - 调用SSRS服务或ReportViewer时使用身份模拟:
// 给ReportViewer设置凭据 ReportViewer1.ServerReport.ReportServerCredentials = new CustomSSRSCredentials(userIdentity); // 调用SSRS服务获取报表列表 using (var impersonationContext = userIdentity.Impersonate()) { var rs = new ReportingService2010(); rs.Url = "http://ssrs-server.domain.com/ReportServer/ReportService2010.asmx"; rs.Credentials = CredentialCache.DefaultCredentials; // 执行报表查询操作 impersonationContext.Undo(); }
4. 备选方案:Azure AD Application Proxy
若Kerberos配置复杂,可通过Application Proxy发布本地SSRS:
- 将SSRS的Web门户和ReportServer服务通过Application Proxy发布到Azure,配置SSO为Kerberos约束委派。
- Azure App Service的Web应用直接使用Application Proxy发布的SSRS地址,ReportViewer凭据设置为
DefaultCredentials即可自动传递用户身份。
关键注意事项
- 本地SSRS需已基于域用户配置好细粒度权限,确保传递的用户身份能匹配SSRS的访问控制规则。
- Azure App Service需通过VPN/ExpressRoute或Application Proxy实现与本地内网的连通。
- Kerberos配置需确保SSRS服务器的服务主体名称(SPN)已正确注册在域账户下,避免身份传递失败。
内容的提问来源于stack exchange,提问作者Hristo Atanasov
相关产品推荐
相关产品推荐

