I have an windows forms application which I'm migrating from MySql to MsSql. In MySql we are using database users for every user. So every user connects to the database using their own account. This is not what we want, because in the future we want the application set open to the world and database users is not a thing on the wishlist. So this is going away.
The problem is that many views work with a function which uses CURRENT_USER() to give access to records (because users are part of a department and are not allowed to see all records of all departments).
In MsSql we are using just one type of connectionstring, but every application connects the database directly. Is it possible in MSSQL to store variables per connection so I can identify a user in the view by the variable I set after creating the connection?
So it would be like this:
Start application
Users logs on
Application creates connection with mssql
Application sets a variables on sql-server
User opens a screen with a view
SQL server returns the view using the variable that has ben set earlier to only return the allowed records to view.
So every user must have it's own variable. Is that possible?
Application is build with NET and iBatis. Not the best combination, but iBatis is to much integrated to throw it all overboard.
While this may or may not be possible, it's definitely not the right way to go. As you said, you're using a single connection string, and likely using a pool of connections to access the database. As you want users to be able to pick any available connection in the pool to do their queries, you don't want any user state (or any state at all for that matter) to be tied to the connection.
As you're opening up to the world, you don't want the application to directly connect to the database. Instead, you should implement middleware that will handle authentication and access rights, and only return data from the database that the user may access. So instead of
user application <- iBatis -> MSSQL
you'll have:
user application <- HTTP/something else -> API <- iBatis -> MSSQL
This is the approach taken used by websites as well. In addition, you'll be able to add functionality like caching, connection pooling etc. to the API, making it possible to support more users.
Related
My objective is to prevent direct user access to the database server. One way is to create a WCF service or web service in the middle between the front end application and the database server.
First of all, the users will be authenticated to the application. Subsequently the application will connect through the WCF service to perform business logic operations. The WCF service will perform the database related operations by using one windows account. This will prevent other users to directly access the database server, since the permission will only be granted to specific one windows account.
Here are my questions : Even though the database access is only granted to one windows account and the WCF will use this windows account to perform database related operations, is it possible to mark all database related operations with the credential of the logged in user ?
Update
Thanks for the replies. Seems like the above scenario is not achievable. I am currently exploring the SQL 2008 Application Role feature. One of the example is here. But after further exploration, apparently there is an issue with the connection pooling.
Update
There is a stack overflow thread here regarding SQL Server Application Role
You'd have to have every user set up in sys.server_principals to enable context switching like EXECUTE AS which would mean that they have direct db access anyway.
If you enabled kerberos/delegation, the same applies. Links One and Two
You'd have to pass in the user name as a parameter on each SQL call, or use CONTEXT_INFO perhaps.
Note: every MS Office user has MSQRY32.EXE which acts as a query tool. If you want no direct DB access, then you need to ensure there are no permissions set or granted
Depends.
If your database and WCF service are on the same box and you do a lot of jiggery pokery to impersonate then it is possible. As soon as you move your DB to another box then it stops working.
This is a known limitation and the reason is impersonation will create a token which will get you to a box but this is not passable to another box. I tried to find the Q&A where MS guy had answered but still havent been able to. Whenever I find it, will update.
We have an application that uses Windows authentication to authenticate users with the database, and the SQL Server user accounts need to have certain read/write access to database tables.
The trouble is that the users can then install SQL Server Management Studio and potentially use the database in ways it's not supposed to be used, which isn't what I want.
Everything that I have read says that using integrated authentication is more secure but at the moment, any user can use Management Studio or Access/Excel to just connect to the database.
I have read question SQL Server Authentication or Integrated Security?, which suggests some workarounds, but I don't really have the option of changing the app as drastically as re-factoring all of the stored procedures etc. so I was hoping there might be another option?
Thank you,
NIco
Everything that I have read says that
using integrated authentication is
more secure
--> It's more secure in a way because it's more difficult to get the password.
If you use SQL Server authentication, the connection string contains user and password. If you know where the connection string is (often in a config file), you can open it and see user and password.
On the other hand, if you use Windows authentication, the connection string just says "Integrated Security=True" and you connect to the server with your Windows account, with the actual password buried somewhere deep in Windows' guts and more difficult to retrieve.
Of course, the big downside of Windows authentication is that if your users need write permissions on a certain table for your application, this means that they can write to the same table with ANY other application as well.
There are some workarounds, but none of them is THE silver bullet:
If your app only needs certain tables of the DB, you can just give permissions on these. So at least, the users can't do stuff in all the other tables
If the users are not allowed to access any tables at all from outside your application, there are unfortunately only two things you can do:
Change your app to SQL authentication and remove all permissions for Windows users
(you can also use a proxy service like Will Hughes suggested, but the effect is the same when the app accesses the DB directly...the point is that your users' Windows accounts don't have any permissions anymore!)
Create views and stored procedures (if they don't already exist anyway) for the stuff your app can do with the database. Give the users permissions to use these, and remove the permissions to the real tables.
--> the users can access the views and SPs directly with other tools (even if they don't have any permissions on the underlying tables...permissions on the views and SPs are enough), but they can't do anything that they can't do in your app as well.
If you don't want users to have access to your database, don't grant them access.
If you need to control what they can do - then you should do your access control in a webservice (or some other form of proxy service), which will then execute approved queries, return data, etc.
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 have a database which users should not be able to alter data in unless they use the specific app. I know best practice is to use windows authentication however that would mean that users could then connect to the database using any other data enabled app and change values which would then not be audited.
Unfortunately SQL 2008 with its inbuilt auditing is not available.
Any ideas how to ensure that users cannot change anything unless its through the controlling app?
Use whatever means for users to log in. Windwos authentication encouraged.
make sure the user has no rights to change any data ;)
The application then, on the existing connection, post-authorized using application roles.
More info on that is on http://msdn.microsoft.com/en-us/library/bb669062.aspx
Basically the application can get a separate sets of rights by using an application password (that sadly has to be coded into the application - use sensible means to protect it), replacing the limited rights the user has with more rights for itself.
I would ask you to consider using an application server, but if you have a classical client/server architecture that is as good as it gets.
So far, after creating DB with all the schema, all I have done so for was accessing them (tables) by reference through ConnectionStrings.
Now, twice, I've read that it's better to create a DB user and access the DB trhough that user by including him in the connectionString.
I'd like to know why so?
Thank for helping
Your question isn't that clear. It seems that you're asking if it is better to use windows security ("Integrated Security=SSPI" in the connection string) or a username/password ("User ID=myUsername;Password=myPassword;").
Its always better to use windows security. Having login information within the connection string is a security risk. Its in cleartext (unless you take some complicated steps to secure that section), and is sent across the wire as cleartext unless you set up a trusted connection between application and server.
Is it better to "create a db user and access the db trhough that user by including him in the connection string?" No. Its better to create a sql server login for user's windows identities and let them use those credentials to access the server.
You do this if you wish to connect as a specific user, rather than (for example) just using the context of the current user which your application is running under. However, if you use SQL Server authentication (i.e. username and password), you'd need to provide that password in the connection string, which is something of a security problem.
If the application has a group of anonymous users (or manages users/passwords itself) then its better to use a Windows login and run the application under a service account (which has minimal required access to the database).
If you're running an interactive application on the desktop, you should let those users connect to SQL server in their own context, by adding them to SQL Server with the required rights (e.g. db read/write , remove any higher functions). Obviously you would use groups to make administration simpler rather than adding individual users.