You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server 2016 SP2无法授予CREATE LOGIN权限问题咨询

问题解答

SQL Server 2016是否支持GRANT CREATE LOGIN?

SQL Server 2016及更早版本不支持GRANT CREATE LOGIN这个独立权限,该权限是在SQL Server 2019才正式引入的(包含后续的2022版本),所以你在2016执行该语句会报语法错误。

在SQL Server 2016中实现需求的方案

要让用户仅能创建新登录名、修改自己创建的登录名,且无法访问现有登录名,需要通过权限授予+DDL触发器+自定义视图组合实现:

1. 授予基础权限

首先授予用户创建登录名所需的最低权限(2016中只能用ALTER ANY LOGIN,后续通过触发器限制其操作范围):

GRANT ALTER ANY LOGIN TO [loginname];

2. 记录登录名的创建者

在master库中创建表,用于存储每个登录名的创建者信息:

USE master;
GO
CREATE TABLE LoginCreators (
    LoginName sysname PRIMARY KEY,
    CreatorLogin sysname NOT NULL,
    CreateDate DATETIME NOT NULL DEFAULT GETDATE()
);
GO
-- 允许目标用户操作该表,用于触发器写入和查询
GRANT INSERT, SELECT ON LoginCreators TO [loginname];

3. 创建服务器级DDL触发器

通过触发器拦截非法操作:创建登录名时自动记录创建者;修改登录名时验证当前用户是否为该登录名的创建者,非创建者操作则回滚:

USE master;
GO
CREATE TRIGGER RestrictLoginAlter
ON ALL SERVER
FOR CREATE_LOGIN, ALTER_LOGIN
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @EventData XML = EVENTDATA();
    DECLARE @LoginName sysname = @EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname');
    DECLARE @CurrentUser sysname = SUSER_SNAME();

    -- 记录新登录名的创建者
    IF @EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)') = 'CREATE_LOGIN'
    BEGIN
        INSERT INTO LoginCreators (LoginName, CreatorLogin)
        VALUES (@LoginName, @CurrentUser);
    END
    -- 验证修改登录名的权限
    ELSE IF @EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)') = 'ALTER_LOGIN'
    BEGIN
        IF NOT EXISTS (SELECT 1 FROM LoginCreators WHERE LoginName = @LoginName AND CreatorLogin = @CurrentUser)
        BEGIN
            RAISERROR('你只能修改自己创建的登录名。', 16, 1);
            ROLLBACK TRANSACTION;
        END
    END
END
GO

4. 限制对现有登录名的访问

拒绝用户查看系统视图sys.server_principals的权限,防止其访问所有登录名:

DENY SELECT ON sys.server_principals TO [loginname];

5. 提供自定义视图让用户查看自己创建的登录名

创建视图仅返回用户自己创建的登录名,并授予查询权限:

USE master;
GO
CREATE VIEW MyCreatedLogins
AS
SELECT sp.name, sp.type_desc, sp.create_date
FROM sys.server_principals sp
JOIN LoginCreators lc ON sp.name = lc.LoginName
WHERE lc.CreatorLogin = SUSER_SNAME();
GO
GRANT SELECT ON MyCreatedLogins TO [loginname];

内容的提问来源于stack exchange,提问作者rgorr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:56:23