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.