登录触发器实现SQL Server 限制IP登录

一、 背景

  MySQL由 usename+host 构成用户,在SQL Server没有这样的机制,那SQL Server如何实现类似的安全控制的功能呢?

本文将介绍5种运用登录触发器实现安全控制的场景

  • 限制某登录名(比如sa)只能在本机或者指定的IP中登录;
  • 限制服务器角色(比如sysadmin)只能在本机或者指定的IP中登录;
  • 限制某登录名(比如sa)只能某时间段内登录;
  • 限制登录名与IP的对应关系,支持多对多关系;
  • 限制某登录名可以在某IP段登录(比如192.168.1.*)
  • 限制只能由SSMS连过来 

 

二、 实现代码

1. 限制某登录名只能在本机或者指定的IP中登录

创建登录触发器:tr_connection_limit,它会在用户登录的时候触发,通过EVENTDATA()函数返回的客户端的IP,使用ORIGINAL_LOGIN()函数返回的登录名,对IP和登录名进行判断。

  实现以下功能:当登录名是test的时候,若登录IP为本地<local machine>或192.168.1.50,192.168.1.120则允许登录,若是其它IP则登录失败。

--Script1:创建test登录账号
CREATE LOGIN test WITH PASSWORD = '123'
GO

-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <限制test用户只能在本机和指定的IP中登录>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================

CREATE TRIGGER [tr_connection_limit]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
--限制test这个帐号的连接
IF ORIGINAL_LOGIN()= 'test'
--仅允许test在本机和下面的IP登录,否则回滚登录
AND
(SELECT EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)'))
NOT IN('<local machine>','192.168.1.50','192.168.1.120')
     ROLLBACK;
END;

 

关于EXECUTE AS的用法参考:EXECUTE AS (Transact-SQL),ORIGINAL_LOGIN()函数参考:ORIGINAL_LOGIN (Transact-SQL),EVENTDATA()函数用法参考:EVENTDATA (Transact-SQL)

非法ip登录报错如下

 

2. 限制服务器角色(比如sysadmin)只能在本机或者指定的IP中登录

可以做一个IP白名单表,避免后期重复修改触发器。首先创建一个Logon_DB数据库,再创建一个ValidIP表,在表中插入<local machine>和192.168.1.195,表示允许本地和IP为192.168.1.195进行登录,登录的帐号属于服务器角色:sysadmin。

--创建测试数据库
USE MASTER
GO
CREATE DATABASE Logon_DB

--创建IP过滤表
USE Logon_DB
GO
CREATE TABLE dbo.ValidIP (
    IP NVARCHAR(15),
    CONSTRAINT PK_ValidIP PRIMARY KEY CLUSTERED(IP)
);
GO

--插入过滤IP
USE Logon_DB
GO
INSERT INTO dbo.ValidIP(IP) VALUES('<local machine>');
INSERT INTO dbo.ValidIP(IP) VALUES('192.168.1.195');

--创建登录触发器
-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <限制本机和指定的IP登录>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================

CREATE TRIGGER [tr_logon_CheckIP]
ON ALL SERVER
FOR LOGON
AS
BEGIN
    IF IS_SRVROLEMEMBER('sysadmin') = 1
    BEGIN
        DECLARE @IP NVARCHAR(15);
        SET @IP = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)'));
        IF NOT EXISTS(SELECT IP FROM [Logon_DB].[dbo].[ValidIP] WHERE IP = @IP)
        ROLLBACK;
    END;
END;

  尝试sa用户从192.168.1.120登录,报错信息如下

 

3. 限制某登录名(比如sa)只能某时间段内登录

比如业务上某些操作只能在晚上跑的,通过这个登录触发器,可以防止用户在白天操作。

  首先我们创建一个名为nightworker的登录名,再创建一个LogonBlockedLog的登录拦截日志表,接着创建登录触发器:tr_logon_CheckTime,7:00-17:00不允许nightworker帐号登录数据库

--创建nightworker登录账号
CREATE LOGIN nightworker WITH PASSWORD = '123'
GO

--创建登录拦截日志表
USE Logon_DB
GO

CREATE TABLE dbo.LogonBlockedLog (
    [Id] INT IDENTITY(1,1),
    [session_id] SMALLINT,
    [login_time] DATETIME,
    [host_name] NVARCHAR(128),
    [original_login_name] NVARCHAR(128),
    [client_net_address] VARCHAR(48),
    CONSTRAINT PK_LogonLog PRIMARY KEY CLUSTERED(Id)
);

--创建登录触发器
-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <限制登录时间>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================

CREATE TRIGGER [tr_logon_CheckTime]
ON ALL SERVER WITH EXECUTE AS 'sa
FOR LOGON
AS
BEGIN
    IF ORIGINAL_LOGIN()='nightworker' AND
    DATEPART(hh,GETDATE()) BETWEEN 7 AND 17
    BEGIN
        ROLLBACK;
        INSERT INTO [Logon_DB].[dbo].[LogonBlockedLog]
            ([session_id]
            ,[login_time]
            ,[host_name]
            ,[original_login_name]
            ,[client_net_address])
        SELECT
            a.[session_id],a.[login_time],a.[host_name],
            a.[original_login_name],b.[client_net_address]
            FROM MASTER.sys.dm_exec_sessions a
            INNER JOIN MASTER.sys.dm_exec_connections b
            ON a.session_id=b.session_id
            WHERE a.session_id = @@SPID
    END;
END;

测试报错信息如下

拦截报错表记录

 

4. 限制登录名与IP的对应关系,支持多对多关系 

进一步地,可以模仿mysql.User表用法,保存用户与IP对应关系,这样就可以对所有登录用户进行控制了。

--登录名与有效IP对应表
USE Logon_DB
GO
CREATE TABLE [dbo].[ValidLogOn](
    [Id] INT IDENTITY(1,1) NOT NULL,
    [LoginName] [sysname] NOT NULL,
    [ValidIP] [nvarchar](15) NOT NULL,
    CONSTRAINT [PK_ValidLogOn] PRIMARY KEY CLUSTERED ([Id])
 )

--创建唯一约束索引
CREATE UNIQUE NONCLUSTERED INDEX [IX_ValidLogOn_LV] ON [dbo].[ValidLogOn]
(
    [LoginName] ASC,
    [ValidIP] ASC
)

--插入测试数据
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'BARXXX\Administrator', N'<local machine>')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'nightworker', N'<local machine>')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'nightworker', N'192.168.1.48')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'sa', N'<local machine>')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'sa', N'127.0.0.1')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'sa', N'192.168.1.48')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'test', N'<local machine>')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'test', N'192.168.1.120')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'test', N'192.168.1.48')
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'test', N'192.168.1.50')

--创建登录触发器
-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <限制登录名和IP>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================
CREATE TRIGGER [tr_logon_CheckLogOn]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
    DECLARE @LoginName sysname
    DECLARE @IP NVARCHAR(15)
    SET @LoginName = ORIGINAL_LOGIN();
    SET @IP = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)'));
    --判断登录名和IP
    IF NOT EXISTS(SELECT [ValidIP] FROM [Logon_DB].[dbo].[ValidLogOn] WHERE [LoginName] = @LoginName AND [ValidIP] = @IP)
        ROLLBACK;
END;

有几点需要注意:BARXXX\Administrator是Windows 身份验证中操作系统的帐号,需要根据实际情况进行修改;IP中则需要注意<local machine>和127.0.0.1这些特殊的地址,个人还是建议在这个表中加入这些信息的。

 

5. 限制某登录名可以在某IP段登录

如果想进行类似Host like 192.168.1.* 这样的范围过滤可以使用CLR扩展函数对IP进行判断,后面会讲到这种方式。这里使用SQL就能解决的方法,仅供参考。开放登录名nightworker在内网所有IP:192.168.1.* 访问本机的权限。

--插入测试数据
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N'nightworker', N'192.168.1.*')

--创建登录触发器
-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <登录名和IP过滤,支持IP范围规范>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================
CREATE TRIGGER [tr_logon_CheckLogOn_RangeIP]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
    DECLARE @LoginName sysname
    DECLARE @IP NVARCHAR(15)
    DECLARE @ValidIP NVARCHAR(15)
    DECLARE @len INT
    DECLARE @data XML
    DECLARE @blocked BIT;
   
    SET @len = 0
    SET @blocked = 0
    SET @LoginName = ORIGINAL_LOGIN();
    SET @data = EVENTDATA();
    SET @IP = @data.value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)');

    --判断登录名和IP
    IF NOT EXISTS(SELECT [ValidIP] FROM [Logon_DB].[dbo].[ValidLogOn] WHERE [LoginName] = @LoginName AND [ValidIP] = @IP)

    BEGIN
        --是否存在IP范围匹配
        SET @ValidIP = (SELECT TOP 1 [ValidIP] FROM [Logon_DB].[dbo].[ValidLogOn]
            WHERE [LoginName] = @LoginName AND [ValidIP] LIKE '%[*]');

        --如果存在就替换Client的IP
        IF (CHARINDEX('*',@ValidIP) > 0 AND @IP <> '<local machine>' AND @IP <> '127.0.0.1')
        BEGIN
            DECLARE @SubValidIP NVARCHAR(15)
            SET @SubValidIP = SUBSTRING(@ValidIP,0,CHARINDEX('*',@ValidIP))
            SET @len = LEN(@SubValidIP) + 1
            IF(SUBSTRING(@IP,0,@len) != @SubValidIP)
            BEGIN
                ROLLBACK
                SET @blocked = 1
            END
        END
        ELSE
        BEGIN
            ROLLBACK;
            SET @blocked = 1
        END
    END

    --日志记录
    INSERT INTO [Logon_DB].[dbo].[LogonLog]
        ([session_id]
        ,[login_time]
        ,[host_name]
        ,[original_login_name]
        ,[client_net_address]
        ,[XmlEvent]
        ,[Blocked])
    SELECT
        @data.value('(/EVENT_INSTANCE/SPID)[1]', 'smallint'),
        GETDATE(),
        @data.value('(/EVENT_INSTANCE/ServerName)[1]', 'sysname'),
        @data.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname'),
        @data.value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)'),
        @data,@blocked
END;

添加192.168.1.*后

nightworker用户登录通过

sa用户登录拦截

 

6. 限制只能由SSMS连过来

CREATE TRIGGER deny_remote_ssms_trigger
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN()= 'sa' AND 
	(
		SELECT COUNT(*) 
		FROM sys.dm_exec_sessions
		WHERE is_user_process = 1 
			AND original_login_name = 'sa' 
			AND [host_name] != 'XP64'
			AND [program_name] LIKE N'Microsoft SQL Server Management Studio%'	-- 只限制由 SSMS 連過來
	) > 0
    ROLLBACK;
END;
GO

 

 

三、 补充说明

如果在登录触发器中需要读取表[Logon_DB].[dbo].[ValidLogOn],且在ON ALL SERVER后面没有加入WITH EXECUTE AS 'sa',使用test或者nightworker登录就会一直报错,因为test和nightworker没有权限读取[Logon_DB].[dbo].[ValidLogOn]表。而tr_logon_CheckIP之所以不用WITH EXECUTE AS 'sa'是因为这本身就是对服务器角色sysadmin的逻辑处理。

测试本地登录的情况的时候需要测试[.]、[local]、[localhost]、[127.0.0.1]、[ipconfig]里面显示的内网IP地址这五种情况。([.]、[local]、[localhost]在EVENTDATA()的ClientHost标签都是显示<local machine>)

 

参考

Blocking Users by IP

SQL Server 2008中的代码安全(二):DDL触发器与登录触发器

CREATE TRIGGER (Transact-SQL)

登录触发器

Sql server限制IP访问方法

sys.dm_exec_sessions (Transact-SQL)

EXECUTE AS (Transact-SQL)

ORIGINAL_LOGIN (Transact-SQL)

EVENTDATA (Transact-SQL)

浅谈SQL Server 数据库之触发器

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: S7-1200是西门子公司推出的一款中小型PLC控制器,SQL Server是微软公司的一款关系数据库管理系统。 S7-1200具有强大的数据处理和控制能力,可以实现自动化控制和监测功能。它支持多种通信接口,如以太网、串口和WiFi,可方便地与其他设备进行数据交互。 SQL Server是一款企业级的数据库管理系统,具有稳定可靠、安全高效、功能丰富等特点。它能够处理大规模数据,并提供高可用性和备份恢复功能,确保数据的完整性和可靠性。 将S7-1200和SQL Server结合使用,可以实现数据的高效存储和管理。通过使用S7-1200的通信功能,可以将PLC采集到的实时数据传输到SQL Server数据库中,在数据库中进行存储和处理。这样可以实现对数据的长期保存、多样化查询和分析,为企业的决策提供有效支持。 此外,S7-1200还可以通过SQL Server提供的数据库连接功能,实现与其他系统的集成。比如,可以通过编写SQL语句,将PLC的控制逻辑与数据库中的业务逻辑相结合,实现更复杂的控制功能。同时,S7-1200和SQL Server的结合还可以通过Web界面实现远程监控和控制,提高生产效率和管理水平。 综上所述,S7-1200和SQL Server的结合可以为企业提供可靠的数据存储和管理解决方案,实现数据的有效利用和业务流程的优化。同时,这一组合还可以提升生产过程的智能化水平,提高企业的竞争力。 ### 回答2: S7-1200是西门子推出的一款小型可编程控制器,而SQL Server是微软开发的一款关系型数据库管理系统。S7-1200可以通过支持的通信模块连接到不同类型的数据库,包括SQL Server。 使用S7-1200连接到SQL Server可以实现数据在控制器和数据库之间的双向传输。首先,需要在S7-1200上配置通信模块,并确保正确设置与SQL Server的连接参数,例如IP地址和端口号。然后,可以在S7-1200上编写程序来实现SQL Server的数据交互。 通过连接到SQL Server,S7-1200可以发送数据到数据库以存储和处理。例如,可以将传感器数据实时存储到数据库中,以便后续分析和报表生成。此外,S7-1200还可以从SQL Server中获取数据,例如从数据库中读取配置参数或历史记录。 使用S7-1200连接到SQL Server可以带来许多优势。首先,通过将数据存储在SQL Server的关系型数据库中,可以实现更高级的数据处理和查询功能,从而更方便地分析数据。其次,与传统的数据存储方式相比,使用SQL Server可以提高数据的可靠性和容错性。此外,通过将S7-1200与SQL Server连接起来,可以实现对远程数据库的访问,从而方便地将数据共享给其他设备或用户。 总之,S7-1200与SQL Server的结合为工业控制和数据管理提供了一种强大的解决方案。通过将S7-1200与SQL Server连接起来,可以实现数据在控制器和数据库之间的灵活传输和处理,从而提高生产效率和数据分析能力。 ### 回答3: S7-1200 是西门子(Siemens)推出的一款可编程逻辑控制器(PLC),它具有灵活性和可靠性,被广泛应用于工业自动化控制领域。SQL Server 是一种关系型数据库管理系统(RDBMS),由微软公司开发和提供支持。 将 S7-1200 和 SQL Server 结合起来使用,可以实现数据采集、存储和分析的功能。S7-1200 可以通过通讯模块与 SQL Server 进行数据交互,将 PLC 中采集的数据发送到数据库中进行存储。这样可以实现对生产过程中的各种参数(如温度、压力、流量等)进行实时监控和记录。 除了数据采集,S7-1200 还可以通过与 SQL Server 的通讯功能,实现与数据库的数据交互。例如,可以通过 PLC 控制数据库中存储的设备状态或运行模式,也可以通过 PLC 控制数据库中的报表生成或数据查询。 此外,通过使用 SQL Server 的高级功能,如触发器、存储过程和视图等,可以对采集到的数据进行复杂的分析和处理。在工业生产环境中,这些分析结果可以用于预测设备故障、优化生产过程等方面,从而提高生产效率和质量。 总之,S7-1200 和 SQL Server 的结合可以实现工业自动化控制和数据管理的一体化解决方案。它提供了实时监控、灵活的数据交互和高级的数据分析功能,有助于提高工业生产的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值