SQL server Login and User - sql-server

I am confused with Login and User. I found following in articles :
A "Login" grants the principal entry into the SERVER.
A "User" grants a login entry into a single DATABASE.
One "Login" can be associated with many users (one per database).
I can understand it theoretically. But, I think I might not have understood this practically.
I created a Login in my SQL server 2008 management studio by right clicking SERVERNAME=>SECURITY=>LOGIN. The default database was "master". Now, I can log into sql server with this login name and password. I noticed that if I change the default database in Login properties to a specific database, I cannot login again with this credential. I reverted back to "master" and it works. What happened here?
Also, why do we need users? I created a user by right clicking DATABASENAME=>SECURITY=>USERS. I cannot relogin with this user credential. So, what is the purpose we need this for. I can understand the theory of this answer but I need little more explanations to make sense.
Also, I am a .net developer, so I would like to know, what are the credentials provided in sql connection strings. Are they login or user or can be any of these?

The simplest explanation is that the SQL Server login gets you into the server, and the settings on that login control how it works in each database.
Don't worry about the database logins for the moment. You already went to SERVERNAME=>SECURITY=>LOGIN. Let's look at what you do with this login - right click and go into properties if you already created the login. Look under Roles - there are a number of different ones with different purposes on the server. But for an app, generally speaking, the average user should only have the Public role.
As far as the Database login, you go to the Mapping section to point your login to whichever databases it needs access to. When you map the login to the database, this CREATES the database login you saw under DATABASENAME=>SECURITY=>USERS if it does not already exist. The mapping is the most important part though, it's what literally gives the login the ability to see data in the database.
For applications, you're using the server login. If you set up the links to the databases you need in mapping, you don't really need to think about the database level login info.

The login only exists at the server level, which is why it maps automatically to the master database.
Users control access to individual databases. When you create a user, you can map it to a login (see Create User on MSDN for the syntax). If you create a user mapped to the login in the database, you can set it as the default and log in.
One reason this is done is to allow multi-tenant environments where a single server hosts many databases that not everyone who can access the server should be able to access. For example, say we provide services to Company A and Company B, and we host the database for each on the same server. We don't want someone from Company A (or, more importantly, someone who has compromised the credentials of someone from Company A) to be able to access the data for Company B, so we only create a user for the Company A login in the Company A database. Here's a brief code setup for you to experiment with:
-- This script assumes whoever is running it has sysadmin permissions on the instance of
-- SQL Server on which it is running. Do not run this on a production instance.
-- Create a database for each company on the server instance.
create database CompanyA;
create database CompanyB;
go
-- Create a login for each company on the server instance.
-- SQL Server integrated security has it's issues, but it's useful for an example like this.
create login CompanyA_Login with password = 'pa55wOrd1', default_database = CompanyA;
create login CompanyB_Login with password = 'pa55wOrd2', default_database = CompanyB;
go
-- Create a user in the appropriate database for each login.
-- We need to tell the server that we want to use a specific database
use CompanyA;
create user CompanyA_User for login CompanyA_Login;
-- We're granting it dbo for the purposes of our example here;
-- a broad permission set like that is a bad practice.
alter role db_owner add member CompanyA_User;
go
-- Repeat the process...
use CompanyB;
create user CompanyB_User for login CompanyB_Login;
alter role db_owner add member CompanyB_User;
go
-- Create a table in each database and populate it with some data.
use CompanyA;
create table dbo.sensitiveInformation
(
sensitiveInformation NVARCHAR(50) NOT NULL
);
insert dbo.sensitiveInformation (sensitiveInformation)
values ('Oh man, it would be bad if this got out!');
go
use CompanyB;
create table dbo.sensitiveInformation
(
sensitiveInformation NVARCHAR(50) NOT NULL
);
insert dbo.sensitiveInformation (sensitiveInformation)
values ('Oh man, it would be even worse if THIS got out!');
go
-- Now, feel free to log in as either user and see what you can and can't do.
-- You will find that the CompanyA_Login will never be able to access CompanyB's
-- data and vice versa. This allows for secure multi-tenant environments.
-- Once you're done playing around, we'll clean up our samples.
use CompanyB;
drop table dbo.sensitiveInformation;
drop user CompanyB_User;
go
use CompanyA;
drop table dbo.sensitiveInformation;
drop user CompanyA_User;
go
use master;
drop login CompanyB_Login;
drop login CompanyA_Login;
drop database CompanyB;
drop database CompanyA;
If you need separate, discrete security/permission sets, and you need one user to have more than one of these sets, you want to use database roles. This article from Tech Republic gives a decent gloss of the benefits of roles, though I'd recommend checking MSDN for the most current ways of creating them.

Related

Login and user is not there IN SQL Server 2017 then why in T-SQL it shows up?

Suppose I have a login metamanager\test which shows when I execute T-SQL, but it is not there when when I expand Security -> Login in SSMS.
Same with a database user.
I try to replicate but failed
use master
select * from sys.syslogins is used for login
use DB
select * from sys.sysusers is used for database user
A LOGIN and a USER are completely different objects.
A LOGIN is a server object, and appear in sys.syslogins, as you see.
A USER is a database object, and for a LOGIN to have access to a database, it needs to have a USER mapped to the LOGIN in that database. A LOGIN with no mapped logins in any databases, and without any server level roles, will be unable to access any of the database on the instance, apart from those that the public roles has in tempdb and master.
It appears, here, you need to create the user in the database, and then give it the appropriate permissions. You can create the USER with the following:
USE {YourDatabase};
GO
CREATE USER 'metamanager\test' FOR LOGIN 'metamanager\test';
You'll need to give it the appropriate permissions afterwards.
Also, after you have created the user, ensure you have refreshed your object explorer. Object explorer doesn't automatically refresh after you create an object.
Not sure if you explaining it correctly, but syslogins and server_principals are about the same. Only the difference that server_principals include "Roles".
As far as I know it is impossible to have something in syslogins, which does not exist in server_principals.

What are good practices for granting database permissions to a web service connection?

I have been searching for articles and SQL script examples that would demonstrate how to securely and conveniently solve one of the most common scenarios - connecting from a .Net Core Entity Framework based web application to an SQL database.
But somehow I could not find any coherent step-by-step guide from a reputable source.
Let's assume the following:
I cannot use integrated Windows auth in the connection string and must use username and password based auth (because hosting on a Linux server and the DB is on a different Windows server)
the web service will need your usual minimum set of permissions - connect to the database, read data, write data, delete data, execute stored procedures
While reading many tutorials, I find there are multiple ways to manage the connection permissions. To avoid this question being too broad, I'll list my current choices as I understand them (please correct me if I'm missing something).
Users and logins:
create a login and a user for the database
create a database-only user without a login (not sure if this is applicable to a web app and connection string, but still it's a feature that I've seen being used)
Assigning permissions:
assign the user to some fixed SQL role (db_datareader, db_datawriter AND also will have to grant EXECUTE permission)
grant all fixed permissions
create a custom role (let's say, db_web_apps) with required permissions
Which choices are better (more secure and easier to manage in general) and recommended by SQL DBAs?
I think every database administrator should have a template script handy for quickly adding a new user with minimum required permissions every time when developers ask for a new connection for their shiny new web app.
If you know a good, reliable tutorial or GitHub / Gist example that explains what and why is being done that way or a script that you yourself have used for years without any issues in production environments, I'll really appreciate if you could share it.
Create a role in the database and assign the required privileges to the role. Don't use the fixed database roles. Instead grant permissions directly to objects, schemas, or the entire database if necessary. Like this:
create role trusted_app_role
grant select, insert, update, delete, execute
on schema::dbo to trusted_app_role
That will grant the role full DML permissions on all the objects in the default dbo schema. So if you have any tables or procedures you don't want the app to have access to, just create them in a different schema, say, admin. This way you never have to fiddle with permissions as you add objects. The fixed database roles predate schema-based permissions, and aren't really needed any more.
For your application's identity, add Active Directory or Azure Active Directory (Azure SQL) identities to this role, or, if you can't, add SQL Users to the role.
If you are on Azure SQL, you should normally use a database user without a login. On SQL Server you can only add "contained database users" if you enable Partial Database Containment. Which you can do, but is incompatible with Change Tracking and Change Data Capture, so it's a tradeoff.
So normally for SQL Server you still create a login and map the user to the login. EG:
create login web_service_user with password = '5X+jeuAB6kmhw85R/AxAg'
create user web_service_user for login web_service_user
And then add that user to your role
alter role trusted_app_role add member web_service_user

The need of user with out log in SQL Server

what is the need of user with out log in in SQL Server?
There is a contained database. I have created a user who can log into the contained database.
How to port the database to another server without additional user configuration?
Is the "user with out log" is going to help in this context?
Want to know more about users with out log in
Experts..please share your views
Users that don't have a login are users that exist only at the database level and therefore you cannot log in to the server with them.
They can however be assigned permissions and can be used to sign modules within those databases.
The most common uses I see for them during my day to day work are either loginless users that are created from a certificate which is then used to sign stored procedures, this means that the user actually logging in to SQL server requires very few permissions in the database and all the work is done in the context of the loginless user, helping to increase security.
I also see loginless users that are not created from certificates, but are made owners of schemas or procedures which then execute as owner, similar to the above, this means that the user lgging in only needs execute rights on the procedure, no table access at all.

What SQL Server Login is used for SQL Server Authentication?

I am trying to figure out what SQL Server Login gets used when I connect to SQL Server, in code, via a connection string that specifies Integrated Security=No and then specifies a user and password.
Note that I don't mean the user I'm specifying (I do know that of course), but the login that user maps to. I'm just now reading about logins vs users in SQL Server, and one point that is hammered home is that you always, always, always need a login to connect, and then a user per database that login needs to access. So I am looking in SSMS for the login that maps to the user I always specify on the databases I care about, but I see no such login.
Fyi, the reason I am asking, is I need to permission a new legacy app for this database, and the app is coded to use SQL Server authentication. I am trying to determine if I simply need users on the necessary database, or if I need to create a login. But now I've gotten myself curious about the general question itself.
Edit - a quick query of syslogins shows only 2 logins. So, my theory that SQLS was maintaining trivial '1 per user' logins but SSMS was hiding them, appears not to be the case
Edit - Querying syslogins, or sys.server_principals, appears to be misleading. On a database for which I have 2 different working SQLS (not Win) logins, I logged in as each and did select * from sys.server_principals. Two different answers: each time I got sa and the login I was logged in as. I would not see the 'other' login, though it was clearly there. I am guessing this may have something to do with schemas, which I also know little about. In any case, I am guessing that generally, logins do in fact exist for all users, though I will not see all these logins when I connect to SSMS as any one login. Does this sound right?
Solved (sort of)
From playing around, on a database on which I have sa, it is clear that SSMS only shows you all logins if you are sa, or perhaps have that specific permission. Otherwise, your view of logins is restricted. Therefore there is no real mystery as to why I was not seeing logins I was expecting. Apparently SSMS hides them. I say 'sort of' and 'apparently' because I never came across anything documenting this. It is just an observation.
Thanks to all for your help.
It is a server-level login unless you are connecting to a contained database. If you mean the database user that the server-level login maps to, you can find out using:
SELECT u.name
FROM sys.server_principals AS l
INNER JOIN sys.database_principals AS u
ON l.sid = u.sid
WHERE l.name = 'user id in your connection string';
If you are not using a contained database, this is how you would provision your user:
USE master;
GO
CREATE LOGIN your_login_name
WITH PASSWORD = 'f00b#r!', CHECK_POLICY = OFF;
GO
USE your_database;
GO
CREATE USER your_login_name -- doesn't have to match, but should for sanity
FROM LOGIN [your_login_name];
GO
-- then apply permissions of course.
In general logins maps to a database user
So for instance if by some unfortunate circumstance the app expected database owner access
You'd create this here login on the server (if it's not already there) and then map it to the dbo user in the database in question.
If it's not a built in user, then you are going to have to look at a db that this legacy app can already access, find out which user it's mapped to
Create that user on your new DB, set the required permission roles etc
Then map the login to it.
There are some subtle differences between sql server versions, so it's hard to do a step by step
If the user the apps login maps to is a custom one, then you are going to have to figure out an equivalent in the new database. Doesn't have to have the same name though (unless the app is using that) and it could even have more permissions.

How to disable SQL Server Management Studio for a user

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.

Resources