在sql Server中添加供應(yīng)用程序使用的帳號

在之前客戶咨詢案例中,很多客戶應(yīng)用程序連接sql server直接用的就是sa帳號。如果對數(shù)據(jù)庫管理稍微嚴格一點的話,就不應(yīng)該給應(yīng)用程序這種權(quán)限,通常應(yīng)用程序只需要進行增刪改查,而很少有ddl操作,因此配置帳號時應(yīng)該遵循“最小權(quán)限分配”的原則僅僅賦予所需的權(quán)限。

??? 對于應(yīng)用程序來說,最小的權(quán)限通常就是就是給予讀權(quán)限,寫權(quán)限和執(zhí)行存儲過程權(quán)限。由于為了防止sql注入導(dǎo)致的數(shù)據(jù)庫信息泄漏,則還需要考慮拒絕帳號的查看定義權(quán)限,但值得注意的是,如果拒絕了查看定義的權(quán)限,則Bulk Insert會失敗。完整的權(quán)限定義如下:

ALTER?ROLE?[db_datareader]?ADD?MEMBER?用戶名  ALTER?ROLE?[db_datawriter]?ADD?MEMBER?用戶名  grant?execute?to?用戶名  deny?view?definition?to?用戶名

?? 在SQL Server中,實例級別的是登錄名,而數(shù)據(jù)庫級別的才是用戶名,登錄名在創(chuàng)建完成后可映射到具體的庫。因此我寫了一個完整的腳本,同時創(chuàng)建登錄名,用戶,以及賦予對應(yīng)的權(quán)限,腳本如下:

--創(chuàng)建用戶的存儲過程,?  --示例EXEC?sp_CreateUser?'UserName','rw','DatabaseName'?  --EXEC?sp_CreateUser?'tesefx','r','Test','0xE39CA97EBE03BB4CA5FF78E50374EEBB'?  CREATE?PROC?sp_CreateUser?  @loginName?VARCHAR(50)?,?  @IsWrite?VarCHAR(3)?,?  @DatabaseName?VARCHAR(50),?  @Sid?VARCHAR(100)?='1'?  AS?  PRINT('示例:EXEC?sp_CreateUser?''UserName'',''rw'',''DatabaseName''')?  PRINT('示例:EXEC?sp_CreateUser?''UserName'',''rwv'',''DatabaseName'',''0xE39CA97EBE03BB4CA5FF78E50374EEBB''')?  PRINT('r為只讀權(quán)限,rw為讀寫權(quán)限,rwv為讀寫加View?Definition權(quán)限')?  IF?EXISTS?(?SELECT?name?  FROM?sys.syslogins?  WHERE?name?=?@loginName?)?  BEGIN?  PRINT?N'登錄名已存在,跳過創(chuàng)建登錄名步驟'?  END?  ELSE?  BEGIN?  DECLARE?@CreateLogin?NVARCHAR(1000)?  DECLARE?@pwd?VARCHAR(50)?  PRINT?@Sid?  SET?@pwd=NEWID()?  IF(@sid='1')?  BEGIN?  SET?@CreateLogin?=?'CREATE?LOGIN?['?+?@loginName?+?']?WITH?PASSWORD=N'''?  +?@Pwd?  +?''',?DEFAULT_DATABASE=[master],?CHECK_EXPIRATION=OFF,?CHECK_POLICY=OFF;'?  PRINT?N'登錄名已創(chuàng)建,密碼為:'+@pwd?  END?  ELSE?  BEGIN?  SET?@CreateLogin?=?'CREATE?LOGIN?['?+?@loginName?+?']?WITH?PASSWORD=N'''?  +?@Pwd?  +?''',?DEFAULT_DATABASE=[master],?CHECK_EXPIRATION=OFF,?CHECK_POLICY=OFF,sid='+@Sid+';'?  PRINT?N'已經(jīng)使用SID創(chuàng)建登錄名:'+@loginName?  END?  EXEC?(@CreateLogin)?  --DECLARE?@sidtemp?NVARCHAR(50)?  --SELECT?@sidtemp=sid?FROM?sys.server_principals?WHERE?name=@loginName?  --PRINT(N'登錄名為:'+@loginName+N'?SID為:?0x'+CONVERT(VARCHAR(50),?@sidtemp,?2)?)?  END?  DECLARE?@DynamicSQL?NVARCHAR(1000)?  --切換數(shù)據(jù)庫上下文?  SET?@DynamicSQL?=?N'Use?['?+?@DatabaseName?+?'];?'?+?'IF?EXISTS(SELECT?name?FROM?sys.database_principals?WHERE?name='''+@loginName+''')?Begin?Print(''用戶名已存在,跳過創(chuàng)建用戶名的步驟'')?end?else?begin?CREATE?USER?['?  +?@loginName?+?']?FOR?LOGIN?'?+?@loginName?+?'?end;IF?('''?  +?@IsWrite?  +?'''=''rw''?or?'''?  +?@IsWrite?  +?'''=''rwv'')?BEGIN?ALTER?ROLE?[db_datareader]?ADD?MEMBER?'?+?@loginName?  +?';ALTER?ROLE?[db_datawriter]?ADD?MEMBER?'?+?@loginName?  +?';?END?ELSE?BEGIN?ALTER?ROLE?[db_datareader]?ADD?MEMBER?'?  +?@loginName?+?';?  ALTER?ROLE?db_datawriter?DROP?MEMBER?'?  +?@loginName?+?'?  ;End;grant?execute?to?'?+?@loginName?+?';?  if('''+@IsWrite+'''''rwv'')?begin?deny?view?definition?to?'?+?@loginName?+?';?end?else?begin?grant?view?definition?to?'?+?@loginName?+?';?end'?  EXEC?(@DynamicSQL)

?? 該存儲過程用于創(chuàng)建應(yīng)用程序連接SQL Server所需的登錄名,用戶以及對應(yīng)權(quán)限,當用戶或登錄名存在時還會跳過該步驟,使用該存儲過程的示例如:?

EXEC?sp_CreateUser?'UserName','rw','DatabaseNam'  EXEC?sp_CreateUser?'tesefx','r','Test','0xE39CA97EBE03BB4CA5FF78E50374EEBB'

??? 上述執(zhí)行的第一行是創(chuàng)建一個標準的帳號,賬戶名UserName,賦予對DatabaseNam的庫的讀寫權(quán)限,并返回生成的GUID密碼。第二個存儲過程是使用第四個參數(shù)sid創(chuàng)建登錄名,由于在AlwaysOn或鏡像的環(huán)境中,兩端登錄名需要有相同的SID,因此提供了在該情況下使用SID創(chuàng)建登錄名的辦法。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊11 分享