3

We have a .NET 4 web application running on our intranet. When a user starts the application, the user's Windows creds are checked to ensure the user is a member of the correct Active Directory groups. If all goes well, the user is sent to our application page and they can begin working.

The web application connects to the database through a generic service account (an account with limited abilities for doing things as a generic user). The system works fine. The user edits are logged.

The problem is the user name being logged. The user name that gets logged is the name of the service account, not the name of the user. As you can imagine, this makes audits quite useless. Yes, we can tell a change was made and when the change was made and even what the change was but we can't tell who made the change.

Some background - This project was started years ago and, at the time, built on SQL Server 2005. At that time, the lead developer concluded it wasn't possible to passthrough the Windows username to the database and get it to log the user name properly. The decision was made to "live with it" and re-evaluate when we moved to SQL Server 2008.

So, we're now on SQL Server 2008 and I'm re-evaluating. The lead dev is no longer here.

How do I continue using my service account but log the Windows account name? We don't want to create SQL accounts for each user.

UPDATE 1 - I left out a critical detail. All the change logs we generate are trigger based. The audit records are generated by the database via triggers whenever a change occurs, not through SQL code in the web app.

Joe
  • 2,017
  • 4
  • 19
  • 21
  • Are your connections pooled or are they established for each operation? As in, will only one user use a connection for that connection's entire lifetime? – Tim Lehner Jan 31 '12 at 17:15
  • In my trigger-based audit logic I grab suser_sname(), host_name(), and app_name() to capture as much info as I can, though this may not help you get relevant data from your web app. – Tim Lehner Jan 31 '12 at 17:30
  • @ Tim Lehner - When I use `suser_sname()`, I'm still getting the name of the service account. – Joe Jan 31 '12 at 18:21
  • Correct, but have you looked into my answer about using CONTEXT_INFO to pass the username to SQL Server? You'll have to pass this info somehow, as SQL Server can't possibly know which user is using the web app. I'm suggesting setting CONTEXT_INFO after establishing a connection rather than redesigning all of your stored procs to take a username parameter or creating SQL logins for every windows account. – Tim Lehner Jan 31 '12 at 19:18
  • Gotcha, I understand the db has no idea of the logged in user. I'm still trying to wrap my head around how this gets passed to the db. – Joe Jan 31 '12 at 20:36

2 Answers2

0

You will need to do this through code on your intranet. Since ASP.Net runs in it's own context of the w3worker process, it will always appear as that account to the SQL server.

Use either Page.User.Identity.Name or the more complete System.Web.HttpContext.Current.User.Identity.Name.

Get the username of the user accessing ASP.NET intranet page within local network

Community
  • 1
  • 1
Bill Martin
  • 4,825
  • 9
  • 52
  • 86
0

Depending upon how your application maintains DB connections, you could pass the username into SQL Server's CONTEXT_INFO each time you connect to the DB from your app.

-- Set a username in CONTEXT_INFO after each connection to the DB:
declare @context_info varbinary(128) = cast(N'username' as varbinary(128))
set context_info @context_info

-- Grab this info at any time in your sql procs:
select cast(context_info() as nvarchar(64)) as CONTEXT_INFO

UPDATE: I've changed this to use nvarchar and also only show Microsoft's preferred method for retrieval of CONTEXT_INFO (the context_info() function). The system views seem like they can be out of date under certain conditions.

Tim Lehner
  • 14,813
  • 4
  • 59
  • 76