I have been playing around with database security recently and a question over at ASK regarding controlling access to database objects has prompted this post.
It is regarded a best practice to lock down your SQL Server instances from unwanted access. As SQL Server offers so many features, there are many facets of the system that need to be adjusted to reach the goal of a watertight system.
Removing user access to your tables is one of a number of ways of guarding your data. If they cannot access the tables, then they have an extra roadblock in accessing and breaking your data. Once this access is revoked, you can then go about granting access to these tables through other objects: vies, functions, stored procedures that give a layer of abstraction from the data and allow a tighter control over user access.
This would also allow you to build up a data access layer (DAL) that would move the database design towards the more traditional programming techniques applied in object oriented programming (OOP). A DAL offers you the benefit of making structural design changes that are transparant to anyone or anything that is accessing the DAL, similar to interfacing between objects in OOP.
There are plenty of resources on this topic but this may give someone, somewhere a start off in the right direction. Below is a test script that will create a test user, a table and a view that accesses the table. The test user has access rights revoked to the table itself, but is allowed to access a subset of the table columns through the test view.
/* Create a test user without a login for this example only */
CREATE USER TestUser WITHOUT LOGIN ;
/* Create a test table */
CREATE TABLE dbo.TestTable
(Col1 int NOT NULL PRIMARY KEY CLUSTERED
, Col2 int NOT NULL
, Col3 int NOT NULL) ;
/* Deny select rights to TestUser */
DENY SELECT ON dbo.TestTable TO TestUser ;
/* Create a view that selects the first two columns of the test table */
CREATE VIEW dbo.TestView AS
SELECT Col1,Col2 FROM dbo.TestTable ;
/* Grant select rights to TestUser for the TestView */
GRANT SELECT ON TestView TO TestUser ;
/* Impersonate TestUser to inherit his access rights*/
EXECUTE AS USER = ‘TestUser’;
/*Try selecting from the base table – fails*/
SELECT * FROM dbo.TestTable ;
/* Try selecting from the TestView – success*/
SELECT * FROM dbo.TestView ;
/* Revert back to your access rights */
/* Tidy up */
DROP VIEW dbo.TestView;
DROP TABLE dbo.TestTable;
DROP USER TestUser;