登录只存在于服务器级别,这就是它自动映射到主数据库的原因。
用户控制对单个数据库的访问。创建用户时,可以将其映射到登录名(有关语法,请参阅MSDN 上的创建用户)。如果您在数据库中创建一个映射到登录名的用户,您可以将其设置为默认值并登录。
这样做的一个原因是允许多租户环境,其中单个服务器托管许多数据库,并非每个可以访问该服务器的人都应该能够访问。例如,假设我们为公司 A 和公司 B 提供服务,并且我们在同一台服务器上为每个公司托管数据库。我们不希望 A 公司的某个人(或者,更重要的是,一个泄露了 A 公司某人的凭据的人)能够访问 B 公司的数据,因此我们只为 A 公司登录创建一个用户A公司数据库。这是一个简短的代码设置供您试验:
-- 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;
如果您需要单独的、离散的安全/权限集,并且需要一个用户拥有多个这些集,那么您需要使用数据库角色。Tech Republic 的这篇文章很好地说明了角色的好处,尽管我建议您查看 MSDN 以了解创建角色的最新方法。