terug naar overzicht

01/12/16

Insight insight

Microsoft
logo vx, vx company

VX Company

+31 35 539 09 09


01/12/16

Anonymous access to SQL Server Reporting Services (SSRS): Problem Solved!

Recently a colleague asked me how to implement this scenario: An existing web front end application in a DMZ should be able to programmatically render SSRS reports where SSRS was installed on the backend server, while end users themselves should not get access.

Well, just use a hidden network credential when making the call to SSRS you would probably answer.rnrnNope, because the scenario had to deal with two more requirements:rnu003culu003ern tu003cliu003eThe web front-end application should not require any changes. SSRS had been installed on the web-front-end server before but that setup was not considered safe anymore. SSRS had to be installed on the backend server. The existing code assumed default credentials.u003c/liu003ern tu003cliu003eThe web front-end server is not domain joined; the backend server is. By default SSRS uses Windows integrated security, which implies the client application must run inside the same domain.u003c/liu003ernu003c/ulu003ernI was surprised I could not find a working solution within an hour. In this article I will explain how I solved the problem by using a custom authentication provider.rnrnMy first thought was that I should be able to solve the problem by making some configuration changes. Something like: enable anonymous authentication and use a credential I specify. I can do that in IIS, but SSRS is not hosted in IIS anymore and ASP.NET does not provide a similar solution. So this thought turned out to be a dead end.

u003cimg class=u0022alignnone size-full wp-image-22897u0022 src=u0022https://vxcompany.com/wp-content/uploads/2016/12/Frans-blog-1@4x.jpegu0022 alt=u0022u0022 width=u0022533u0022 height=u0022194u0022 /u003e

My second thought was a custom authentication provider. By custom coding you can do everything you want, right? There is a Microsoft product sample for that. When I studied the code I was in shock: there is quite a lot of code involved and even more configuration changes to be made. I hesitated; do I really have to go that way? Well the answer is unfortunately: yes!rnrnLet me elaborate a bit so you can understand why the solution is a bit complicated at first sight.rnu003culu003ern tu003cliu003eYou have to deal with two virtual directories: Report Manager and Report Server. Report Manager uses Report Server web services behind the scenes and therefore depends on Report Server. In my use case, Report Manager is used by administrators only to upload new reports and data sources and setting security on report folders. End users do not have to access Report Manager, because all report requests are made programmatically. So you might think that you don’t have to touch Report Manager. Wrong! Please read on.u003c/liu003ern tu003cliu003eYou cannot mix Windows integrated security with your own authentication mechanism. So when you want to enable anonymous access to Report Server you have to turn Windows integrated security off. And because Report Manager depends on Report Server, you have to turn off Windows integrated security for Report Manager, too! And when you turn off Windows integrated security in Report Manager you suddenly cannot manage your reports and data sources any more, unless you provide all the code for authentication and authorization. Things like: creating a user, validating user names, validating passwords, checking if users have already a session. Furthermore, no Windows security means no standard Access Control List checking! You have to provide code for that too! Do you understand my hesitation to go this way?u003c/liu003ernu003c/ulu003ernFortunately, the Microsoft product sample code is a fully working solution implementing forms based authentication so I could concentrate on making the required changes in the authentication code. In high level, this is what I did:rnu003colu003ern tu003cliu003eGet the Microsoft product sample code, compile it and deploy it to a test server. You can download the code from: u003ca href=u0022http://msftrsprodsamples.codeplex.com/releases/view/72275u0022 target=u0022_blanku0022 rel=u0022noopener noreferreru0022u003ehttp://msftrsprodsamples.codeplex.com/releases/view/72275u003c/au003eu003c/liu003ern tu003cliu003eMake all the configuration changes to enable forms based authentication on the test server. I used this article: u003ca href=u0022http://www.codeproject.com/Articles/675943/SSRS-Forms-Authenticationu0022 target=u0022_blanku0022 rel=u0022noopener noreferreru0022u003ehttp://www.codeproject.com/Articles/675943/SSRS-Forms-Authenticationu003c/au003eu003c/liu003ern tu003cliu003eMake one additional change to allow anonymous user access to Report Server, by simply u003cemu003eremovingu003c/emu003e this line of configuration:u003c/liu003ern tu003cliu003eI added a configuration setting to specify the logon name of the anonymous user in web.config of Report Server.u003c/liu003ern tu003cliu003eCreate that user account using the forms based authentication pages of Report Manager provided by the product sample solution. Note that the sample solution provides one SSRS admin logon name that has fully access. You have to create the account for this SSRS admin logon first and remember the password. Then you can create the account for the anonymous logon using the same page. Then logon using the SSRS admin account to use Report Manager in the usual way.u003c/liu003ern tu003cliu003eAssign the report browser role on your report folders to the anonymous logon account using Report Manager.u003c/liu003ern tu003cliu003eIn the GetUserInfo method of the authentication extension (implementing Microsoft.ReportingServices.Interfaces.IAuthenticationExtension) I added a check to see if the user had already been authenticated. If not, I just returned a new GenericIdentity object containing the name of the anonymous user I had configured.u003c/liu003ern tu003cliu003eCompile and redeploy your solution.u003c/liu003ern tu003cliu003eFinally, when a client application is using the Report Server web service interface to render reports, they get access to all the reports for which the anonymous user account has been granted browser access.u003c/liu003ernu003c/olu003ernAnd this is the magic piece of code in the authentication extension:rnu003ctableu003ernu003ctbodyu003ernu003ctru003ernu003ctd width=u0022604u0022u003epublic void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)rnrn{rnrn// If the current user identity is not null,rnrn// set the userIdentity parameter to that of the current userrnrnif (HttpContext.Current != nullrnrnu0026amp;u0026amp; HttpContext.Current.User != nullrnrnu0026amp;u0026amp; HttpContext.Current.User.Identity != nullrnrnu0026amp;u0026amp; HttpContext.Current.User.Identity.IsAuthenticated)rnrn{rnrnuserIdentity = HttpContext.Current.User.Identity;rnrn}rnrnelsernrn// The current user identity is null. This happens when the user attempts an anonymous logon.rnrn// To configure for anonymous logon, return a GenericIdentityrnrn{rnrnconst string userkey = u0022AnonymousUseru0022;rnrnstring username = ConfigurationManager.AppSettings[userkey];rnrnuserIdentity = new GenericIdentity(username);rnrn}rnrn// initialize a pointer to the current user id to zerornrnuserId = IntPtr.Zero;rnrn}u003c/tdu003ernu003c/tru003ernu003c/tbodyu003ernu003c/tableu003ernTip: if you run Visual Studio as administrator you can attach the debugger to ReportingServicesService.exe set breakpoints and debug the code. Just restart Reporting Services before each new deployment and it will pick up your latest bits.rnrnTip: if you want to prevent end users from accessing Report Manager, configure it listening to a different HTTP port than Report Server and block access through the firewall.rnrnHappy anonymous reporting!

Delen