I have a SQL Server 2008 instance with several databases and I'm currently writing a C# application to access those databases. In this app, the end user can select a database they want to connect to.
I already have a list of all databases on the server, how can I limit that list to those databases the user can log in to? Or, how can I query that list?
There's a lot of databases, but each user can only access some of them, so trying to connect and catching the Exception is probably not a good idea.
Fyi: The server is configured for Windows authentication only, and the logins to the server are created for Windows' user groups (not individual users).
You can query all databases from sys.sysdatabases, and check if the user has access with HAS_DBACCESS:
SELECT name
FROM sys.sysdatabases
WHERE HAS_DBACCESS(name) = 1
Maybe as an alternative to Andomars answer (which I like!) you could interrogate Active Directory to see if the user is a member of a valid group for your database. I suspect this would mean you would have to maintain some Windows Group to Database Name lookup.
You can use the system stored procedure sp_helplogins 'User Name'
Related
We have MS SQL Server 2012 in production use and MS AD.
Let me explain in short what our concept of assigning user permissions is like.
For certain user group that has some access to a certain application we create AD group and assign AD users to it. Since this application needs to access data in other DB, we add that group to that DB as well and set access/execute rights to needed objects (either specific object or schemas).
Since certain people use other applications and DBs, they are added to other AD groups as well. Those groups, by no surprise, need to access some objects to second database too.
So we have situation when certain users are in few different AD groups with different accesses to the same objects in a DB. That causes lots of "strange" behaviors when, all of a sudden, some user gets denied access to objects in DB.
My questions are:
Is there any way to find out with which privileges (through which AD group) some user got access/denial for certain sql query that was triggered from application?
Can someone explain how sql server handles privileges in such environment?
I'm open for any suggestions on how to handle/set accesses differently altogether but not involving reprogramming applications (only DBA site).
Thank you.
Assuming that you're an admin, you can look at sys.login_token, sys.user_token, and sys.fn_my_permissions() while impersonating the user in question to get some idea. Something like:
execute as login='yourDom\User1';
select * from sys.login_token;
select * from sys.user_token;
select * from sys.fn_my_permission('dbo.someObject', 'OBJECT');
revert;
Does anyone know how to fix up orphaned local Windows users in a SQL database?
I'm attempting to backup and restore a database to a different machine. Neither machine is in a domain - they are in different workgroups. Several Windows users have permissions in the database on the source machine and in order to facilitate reconnecting the users in the target machine, I've set up users with the same usernames (but different passwords) there.
Unfortunately this doesn't work. The database users are restored somewhat uselessly not just as [user name] but as [source machine name]\[user name], preventing linking of accounts on the target machine. Does anyone know how it's possible to reconnect those users to the correct windows accounts? I did the usual Googling, but the information available is generally for connecting orphaned SQL users, not for connecting orphaned local Windows users.
A summary of conversations around this subject ...
At our site we "drop" the users and add them back in appropriately. To make this easier on ourselves we have users in a domain group (or groups), and then grant appropriate access priveleges to those groups.
If this (moving databases) is a reasonably common occurrence it's usually best to create a script to do this - a colleague has generated such a script by querying the sysuers table along the lines of
SELECT 'some appropriate text for this user' + name FROM dbo.sysusers where sid is not null.
He then pastes the results of that query into another query window and saves that as the script
You'll need to use sp_change_users_login - the actual call will depend on your version of SQL - here's a link to M/S ref
sp_users_login documentation
and Troubleshott Orphaned Users
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.
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.
Is there a way to prevent users from getting into SQL Server Management Studio so that they can't just edit table rows manually? They still need to access the tables by running my application.
You can use the DENY VIEW ANY DATABASE command for the particular user(s). This is a new feature available in SQL Server 2008.
It prevents the user from seeing the system catalog (sys.databases, sys.sysdatabases, etc.) and therefore makes the DB invisible to them in SQL Management Studio (SSMS).
Run this command from the Master Database:
DENY VIEW ANY DATABASE TO 'loginName'
The user is still able to access the database through your application. However, if they log in through SSMS, your database will not show up in the list of databases and if they open a query window, your database will not appear in the dropdown.
However, this is not fool-proof. If the user is smart enough to run the Query Command:
USE <YourDatabaseName>
Then they will see the database in the Query Analyzer.
Since this solution is taking you 90% there, I would give the database some obscure name not let the users know the name of the database.
You DO NOT need to worry about them having access to the tool. Simply make sure they do not know any of the SQL logins for the specific Databases that have read/write permissions, if they do, change the password. If they have access to the DB via Windows Authentication, make sure that they are in a datareader role. You can use roles to manage what the users can do in SQL.
You can use a trigger.
CREATE TRIGGER [TR_LOGON_APP]
ON ALL SERVER
FOR LOGON
AS
BEGIN
DECLARE #program_name nvarchar(128)
DECLARE #host_name nvarchar(128)
SELECT #program_name = program_name,
#host_name = host_name
FROM sys.dm_exec_sessions AS c
WHERE c.session_id = ##spid
IF ORIGINAL_LOGIN() IN('YOUR_APP_LOGIN_NAME')
AND #program_name LIKE '%Management%Studio%'
BEGIN
RAISERROR('This login is for application use only.',16,1)
ROLLBACK;
END
END;
https://www.sqlservercentral.com/Forums/1236514/How-to-prevent-user-login-to-SQL-Management-Studio-#bm1236562
I would suggest you lock down the database and give appropriate read-only (or other) rights to the user. That way the user can still use management studio to run select queries and such.
If you don't want the user to have any rights at all then you could do that as well.
If your application is running as a service/user account then only that account requires access to the database. The individual users' account do not require any access to the database and therefore they won't even have read access. Your app will be the gateway to the data.
If the users are running the application under their user accounts then grant them read-only permission. You can simply add them to the db_datareader role.
Hope this helps!
You can deny 'Users' access rights to the ssms.exe executable file, while granting the relevant users/administrators rights to it.
If your application only used stored procedures to modify the data, you could give the end users access to run the stored procs, but deny them access to modify the tables.
Don't let them know what the database login is.
If you can't restrict the login, use stored procedures exclusively for updates and disable any CREATE,DELETE,INSERT, or UPDATE permissions for that user.
An Application Role will allow you to secure database objects to your application instead of the logged on user.
I agree with Jon Erickson as a general rule
do not allow any users access to the tables, but only allow access through stored procs
do not allow general user accounts access to stored procs, but only the account your app runs under (whether it's an integrated login or SQL login)
Make well usage of Database Roles, if Users should only have SELECT (read) access assign them the db_datareader Role. Even if they login using SSMS they will can execute only SELECT statements.