I am looking for different ways to uniquely identify an application user in SQL Server 2008.
To give some back ground to the issue:
The ASP.NET 4 web application I work with uses an SQL Server 2008 database, there is one SQL Server login and DB User for all connections from the application to database.
We are developing a reporting solution using Crystal Reports where users can write and execute their own reports through the application. The crystal reports can only return data from Views. Each application user will have their own unique login to the server.
The View then uses SELECT SYSTEM_USER() to find the logged in user and restrict data returned from the view.
Is it bad practice to create a distinct login and DB user for each application user? This would mean > 1000 users per DB, across up to 80 databases (Creation of
each log in would be handled through T-SQL, not manually)
What other ways can the user be identified in the View in the DB?
We looked at altering the connection string to include the user id in the Workstation ID, we can use SELECT HOST_NAME() to get the ID, but this seems like abuse of the Workstation ID.
Any other suggestions about how the user can be uniquely identified would be appreciated.
Many thanks
Have you considered using Windows Authentication as apposed to SQL Authentication? That would at least reduce the number of logins & users that would need to be managed.
Y can use external database,file or other resource to store user access to any data when u use msql 2008.
http://msdn.microsoft.com/en-us/library/dd392015%28v=sql.100%29.aspx
That give y change to not mix data with audit elements for performance and security reasons.
Use profiler on your sql server and in profiler is information about ( aplication , user , and host ). So that kind of information y can easy get by audit or from custom trigger on certain database objects.
Your aplication can also have own user table and share the same connection string too all users or give users with windows auth type only public privilege. And use in stored procedures run as command ( run as another user in db).
So y can log any user and give them minimal rights.
Its my firs post here and I actually learning English lol.
There were two solutions that we came up with:
Before the Crystal report is executed, in .Net we can extract the SQL the report (and sub report) will generate, execute the SQL and put the results in a dataset and generate the report from the dataset. The advantage of this is that because we have the SQL, before the SQL executes, we can supply user information to the SQL server session that can be used to identify the user when the SQL is executing.
Have a limited number of SQL Server user logins which can be dynamically assigned to application users. We will have a table which will map the SQL Server Login to an application user just before they run a Crystal report. When they query has finished executing the Login is released. Obviously this means that at busy times we may run out of Logins, but more can be added depending on usage.
Related
I have a SQL Server instance that has been in place with our company for several years. There is an SSRS site (and reporting database) associated with it where you can run reports from. We now want to be able to Subscribe to reports from that SSRS site.
In order to do so, we need to create a data source that has stored credentials that can run the report. Those credentials need to be set up in the SSRS database I believe. Unfortunately we don't have access to the database to do so.
How can we get a report subscribed in this situation?
You should be able to do this using only the Report Manager interface.
Go to the data source for the report and check the option for "Credentials stored securely on the report server" and supply the 'User name' and 'Password'.
In SQL Server I have a many to many relationship between items and active directory groups. I want to build a query, that based on a supplied active directory user, I would be able to query for all items associated to an active directory group if the user is a member of the group.
I went down the road of using IS_Member, but that only works for the currently connected user. The stored procedure will be called by an asp.net web app, which currently connects with a specific sql user account. I don't think I can connect using integrated authentication and impersonation in the web app, because I don't beleive our infrastructure configuration will allow delegation from the user machine, through the web server, then to the db server (3 hop issue).
What can I do here?
Write a C# or VB.NET .exe that queries AD and populates a table in the database with all the users/groups and call it from a SQL job that you execute daily. Then just use the synched up table data to do the comparisons. This way you can avoid all the other complexity of trying to do it on the fly. Group membership doesn't change that often. Even if something changed in AD you can just manually run your "sync job" and things would be ok. You can use Windows.Identity() or whatever it is from ASP.NET to check the username.
The issue you describe is a classic double-hop scenario, which can be (eventually) resolved through the painstaking process known as Kerberos configuration. A lazier workaround would involve passing the credentials from the asp.net application as a variable to a SQL query on your database.
If the SQL Server has the LDAP Server configured as a linked server, you could rewrite your stored procedures to accept the user as an input variable and check to see if the user is a member of an AD group before proceeding. Consider incorporating OPENQUERY into your stored procedures as shown below:
CREATE PROCEDURE CheckAccess
#CurrentUser varchar(max)
AS
IF #CurrentUser IN
(
SELECT CN
FROM OPENQUERY(ADSI,'<LDAP://DC=Your,DC=DomainComponent,DC=com>;(&(CN=*)
(memberOf=CN=YourADGroupName,OU=Your,OU=OrganizationalUnit,OU=Name,DC=Your,DC=DomainComponent,DC=com));CN')
)
THEN
SELECT 'Authorized User'
ELSE
SELECT 'Unauthorized User'
END
If you can, consult with your LDAP admins to make sure you get the group's correct domainComponents and organizationalUnits to tweak the OPENQUERY. One drawback to this is that it can take a while to query your AD group, obviously depending on the size of membership. It can be a pain, but as long as your app can pass the user as a variable, you can leverage OPENQUERY or even query sys.database_principals to check their access.
My team has a service deployed internally, and part of this service is a list of client accounts stored in a sql table. SSRS is hosted on another server and we have integration jobs which [will eventually] pull these client accounts (along with additional info) from our 3 production environments to this SSRS database.
Also on this SSRS database, I’m creating a new table that will be a mapping of domain accounts and client accounts. I need this table so I can filter my report based on which client accounts the logged on user is allowed to see.
Pretty simple so far.
The next requirement of this is that I need to restrict access to the report itself. I understand I could normally use a security group to do this, but that would result in two separate locations to manage permissions for one resource and this is what I want to avoid.
The solution I’m looking into is to create a security extension to validate the logged in user against the database, allowing them access to the folder/report if they exist in the table. Once in, I can then use that same table again to filter their results.
What I’m not sure of is 1) if this is the best solution and 2) can I use a security extension for just MY portion of the site. There are many other users and reports on this site that I don’t deal with and don’t want to conflict with those.
Could you fill the DB table automatically from AD? Then you can use the standard windows security, but still only do the administration in Active Directory.
link text
You could set up an internal report parameter, called something like UserID, and set its default value to be the non-queried expression =User!UserID . (This user ID can be selected from the list of globals in the Edit Expression dialog.)
You could then add a cartesian/cross join to your users table in your query, with a selection condition based on your internal report parameter - eg. ...and UserTable.ID = #UserID . This would ensure that no records were returned if an unauthorised user was running the report.
Note that the User!UserID field will only return the user for interactively-run reports - in scheduled reports, this will be the account for the scheduling service.
Can't you restrict access to the report by using a security group (either in it's own folder or report level permissions). Use windows authentication in your datasource connection and filter you report retrieving your username using the sql function ORIGINAL_LOGIN?
We have a web application that uses forms authentication to authenticate a user based on a user table in the database. (I.e. no active directory or SQL server user accounts are involved here). The web application accesses the SQL server using a service account. However, for auditing, authorization and other purposes, our stored procedures need to know for which user any given operation is being executed.
In a previous life, I worked with a similar situation using an Oracle database. In this scenario, every time we opened a connection, we first called an Oracle build in procedure to set a connection scoped context variable. This variable contained the user id for the user that would be using the connection. Then all stored procedures that needed to know the current user would check the context variable.
Conceptually this worked a lot like pushing user information onto the CallContext before making a remote call.
My question is, is there any similar mechanism in Microsoft SQL server?
Obvioulsy, if I must, I can pass the UserId as an argument to every single stored procedure, but that is exactly what I am trying to avoid.
Use SET CONTEXT_INFO and CONTEXT_INFO(). See Using Session Context Information.
What you can do is create users within the database (without Server logins) and give them appropriate permissions. After that, what you do is an "execute as" statement and then the user context for your database calls will be as if the user called it. Example:
EXECUTE AS USER = 'user2';
EXECUTE usp_insert_stuff #params;
REVERT;
Downside: you have to set up SQL security and manage users
Upside: Users cannot connect directly to SQL Server and you get auditing.
Reference here:
http://msdn.microsoft.com/en-us/library/ms188354.aspx
See examples towards the bottom of the page.
I'm having a problem with my SSRS 2008 configuration at the moment. This is how we are currently set up.
1 server hosting SQL Server and SSRS, no integration with sharepoint etc. Users access the SSRS web application, and then from there they access the "Report Builder 1.0" too, which they can use to create and run reports based off a reporting model.
This is all done using Windows Authentication - so they login with their domain account to the web application, and then again when loading the Report Builder. Each domain user is configured to be able to login to SQL Server rather than using a generic SSRS account, and all of the above works fine.
The way this is setup means that you can always tell which individual user is logged in and running reports - either to the website or when running reports through report builder. This is a requirement of this application as all users will see slightly different versions of the data models (this is controlled by the underlying views, based off the domain account running the query). So Tom may get 100 rows back from his query but Harry will only get 50, etc.
The Datasource is setup to use integrated security (Which passes through this domain account to SQL Server).
My problem comes when a user creates a report in report builder, and then saves it to the server. When they login to the web application and run the report there - it works fine, but when they try to setup an email subscription, they get this message:
"Subscriptions cannot be created because the credentials used to run the report are not stored, or if a linked report, the link is no longer valid"
A bit of research leads me to think that this is down to the integrated security settings, as for some reason SSRS is ignoring the currently logged on user account or cannot use that to setup the subscription.
Everything works if I set the datasource to use a specific account - but then that breaks the data filtering based on user account (obviously, as it would now be just using one account for everyone!).
Any ideas for how I can approach this? Is there a configuration setting that I can play with to try and get this working using integrated security? Any help/comments are appreciated!
To create a report subscription you must meet a few reqs:
First is,
A report that can run unattended (that is, a report that uses stored credentials or no credentials).
To do what your wanting to do I suggest you setup data driven subscriptions. Heres a link to get you started. Data Driven Subscriptions Theres also several good videos of the basic setup. Like this one sqlLunch #8
Here's another walkthrough that's pretty decent: Walkthrough
Hope any of this helps ya.
Thats a nice one to have in your tool belt as well.
If you just drop the subscribed report into a file share instead of emailing it, the users can fill in their username and password, so it will run as them. The only problem with doing it this way is when they change their password, they will need to go and put the new password into the subscription again.
I guess they could have another account with a password that wont expire to run the report as, but that's probably not good practice
what you could do is have the list of users in a table in the database with what they're permissions are, then set up a data-driven subscription to get the list of users and get their permissions and filter the report accordingly.