在调用存储过程时获取用户的IP地址(SQL)

Prz*_*min 17 sql t-sql sql-server ip stored-procedures

是否有可能,如果是这样,如何获得用户的远程IP地址执行查询,类似于我们可以获得用户的名字:SUSER_SNAME()

在赏金之前更新

我正在寻找一种解决方案,它允许获取普通凡人用户的IP地址,而不是数据库所有者.TheGameiswar或njc提出的想法不允许捕获仅被授予execute权限的用户的IP地址.但是,它们是解决问题的绝佳方法.在这里,我列出了这些想法的精髓:

请看我遵循的顺序:

create procedure MyStoredProcedure as
select client_net_address 
from sys.dm_exec_connections
where session_id = @@SPID
Run Code Online (Sandbox Code Playgroud)

现在添加用户并授予权限:

CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';

GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
Run Code Online (Sandbox Code Playgroud)

当我使用查询运行该过程时:

EXECUTE AS USER = 'user_mortal_jack'
exec MyStoredProcedure
REVERT
Run Code Online (Sandbox Code Playgroud)

我收到错误消息:

正在执行的模块不受信任.需要为模块的数据库所有者授予身份验证权限,或者需要对模块进行数字签名.

即使我授予了额外的许可,我也会收到此消息:

grant VIEW SERVER STATE to [user_mortal_jack];
Run Code Online (Sandbox Code Playgroud)

如果我将存储过程的开头更改为:

create procedure MyStoredProcedure
with execute as OWNER as 
Run Code Online (Sandbox Code Playgroud)

我最终得到了不同类型的错误:

无法获取有关Windows NT组/用户'blahblah\admin_user'的信息,错误代码为0x534.

赏金后更新

赏金被授予Hadi,因为他们的答案中隐藏着这一行代码:

CONNECTIONPROPERTY('client_net_address')
Run Code Online (Sandbox Code Playgroud)

让我们捕获任何凡人用户的IP地址,既不给予用户任何额外的权利,也不设置数据库TRUSTWORTHY ON选项,甚至不创建过程WITH EXECUTE AS OWNER子句.

Had*_*adi 14

基本信息

有两种方法可以获取当前的连接信息

  1. 动态管理视图获取信息

    SELECT
    conn.session_ID as SPID,
    conn.client_net_address as IPAddress,
    sess.host_name as MachineName,
    sess.program_name as ApplicationName,
    login_name as LoginName
    FROM sys.dm_exec_connections conn
    inner join sys.dm_exec_sessions sess
    on conn.session_ID=sess.session_ID
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用CONNECTIONPROPERTY函数(SQL Server 2008和更高版本):

    select
    CONNECTIONPROPERTY('net_transport') AS net_transport,
    CONNECTIONPROPERTY('protocol_type') AS protocol_type,
    CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
    CONNECTIONPROPERTY('local_net_address') AS local_net_address,
    CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
    CONNECTIONPROPERTY('client_net_address') AS client_net_address
    
    Run Code Online (Sandbox Code Playgroud)

建议的解决方案

  1. 如果您要授予用户特定的IP地址

    CREATE PROCEDURE MyStoredProcedure AS
    BEGIN
        DECLARE @IP_Address varchar(255);
    
        SELECT @IP_Address = CAST(CONNECTIONPROPERTY('client_net_address') as varchar(200))
    
        IF @IP_Address = 'XXX.XXX.XXX.XXX'
        SELECT TOP 1 FROM tb
    
    END
    
    Run Code Online (Sandbox Code Playgroud)
  2. 假设您有一个包含授权IP地址的表(即TBL_IP)

    CREATE PROCEDURE MyStoredProcedure AS BEGIN DECLARE @IP_Address varchar(255);

    SELECT @IP_Address = CAST(CONNECTIONPROPERTY('client_net_address') as varchar(200))
    
    IF EXISTS (SELECT 1 FROM TBL_IP WHERE [IP] = @IP_Address )
    SELECT TOP 1 FROM tb
    
    Run Code Online (Sandbox Code Playgroud)

    结束

  3. 如果要授予用户(数据库用户)执行存储过程的权限,则应使用此命令

    在MyStoredProcedure TO用户上执行GRANT EXECUTE;

    有许多详细的文章和答案谈论您正面临的问题,以及许多建议的解决方案,例如在TRUSTWORTHY模式下设置数据库(在使用它之前阅读下面的第一个链接)和信任身份验证器,以及其他方法.您可以在下面的链接中找到它们

    注意:您可以检查@SteveFord答案是否使用了TRUSTWORTHY属性

  4. 如果您希望阻止除特定IP地址之外的连接,那么您应该遵循此答案

    此外,还有许多脚本可用于获取客户端或服务器IP地址,可在以下问题中找到:

参考

  • `CONNECTIONPROPERTY('client_net_address')AS client_net_address`似乎有效,让你成为赏金的候选人.你的答案的某些部分将导致我在我的问题中提到的问题.请考虑审核. (3认同)