Est-il possible, et si oui comment, d'obtenir que l'adresse IP distante d'un utilisateur exécute la requête, de la même manière que nous pouvons obtenir le nom de l'utilisateur avec: SUSER_SNAME()
?
Mise à jour avant prime
Je cherche une solution qui permette de récupérer l'adresse IP d'un utilisateur mortel ordinaire, pas d'un propriétaire de base de données. Les idées proposées par TheGameiswar ou njc ne permettent pas de capturer l’adresse IP d’un utilisateur à qui une autorisation execute
a été accordée. Cependant, ce sont d'excellentes idées pour commencer avec le problème. Ici, je liste l'essentiel des idées:
S'il vous plaît voir la séquence que je suis:
create procedure MyStoredProcedure as
select client_net_address
from sys.dm_exec_connections
where session_id = @@SPID
Maintenant, ajoutez un utilisateur et accordez la permission:
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
Lorsque j'exécute la procédure avec une requête:
EXECUTE AS USER = 'user_mortal_jack'
exec MyStoredProcedure
REVERT
Je reçois un message d'erreur:
Le module en cours d'exécution n'est pas approuvé. Soit le propriétaire de la base de données du module doit être autorisé à s'authentifier, soit le module doit être signé numériquement.
Je recevrai ce message même si j'accorde une permission supplémentaire:
grant VIEW SERVER STATE to [user_mortal_jack];
Si je change le début de la procédure stockée en:
create procedure MyStoredProcedure
with execute as OWNER as
Je me retrouve avec une sorte d'erreur différente:
Impossible d'obtenir des informations sur le groupe/utilisateur Windows NT 'blahblah\admin_user', code d'erreur 0x534.
Mise à jour après la prime
La prime est accordée à Hadi pour cette seule ligne de code cachée dans sa réponse:
CONNECTIONPROPERTY('client_net_address')
qui capturons l’adresse IP de tout utilisateur mortel sans accorder aucun droit supplémentaire à l’utilisateur ni définir l’option TRUSTWORTHY ON de la base de données, ni même créer une clause de procédure WITH EXECUTE AS OWNER
.
Il existe deux manières d'obtenir les informations de connexion actuelles.
Obtention d'informations à partir de Vues de gestion dynamiques
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
Utilisation de CONNECTIONPROPERTY function (SQL Server 2008 et version ultérieure):
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
Si vous souhaitez donner à l'utilisateur une adresse IP spécifique
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
En supposant que vous ayez une table contenant l'adresse IP attribuée (c'est-à-dire TBL_IP
)
CREATE PROCEDURE MyStoredProcedure AS COMMENCE 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
FIN
Si vous souhaitez autoriser un utilisateur (utilisateur de base de données) à exécuter une procédure stockée, vous devez utiliser cette commande
GRANT EXECUTE ON MyStoredProcedure TO User;
Il existe de nombreux articles détaillés et réponses concernant le problème auquel vous êtes confronté, ainsi que de nombreuses solutions suggérées, telles que la définition de la base de données en mode TRUSTWORTHY
(avant de l'utiliser, lisez le premier lien ci-dessous), la confiance en l'authentificateur et d'autres méthodes. Vous pouvez les trouver dans les liens ci-dessous
_ {Remarque: vous pouvez vérifier la réponse de @SteveFord pour utiliser la propriété TRUSTWORTHY
} _
Si vous souhaitez bloquer des connexions, à l'exception d'adresses IP spécifiques, vous devez suivre cette réponse.
De nombreux scripts peuvent également être utilisés pour obtenir des adresses IP de clients ou de serveurs, comme indiqué ci-dessous:}
Références
Utilisation de l'instruction EXECUTE AS OWNER
dans une instruction CREATE PROCEDURE
:
DeMSDN
Lorsqu'un utilisateur exécute un module qui a été spécifié pour s'exécuter dans un fichier contexte autre que CALLER, autorisation de l'utilisateur à exécuter le module est cochée, mais des autorisations supplémentaires vérifient les objets qui sont accessibles par le module sont exécutés sur le compte utilisateur spécifié dans la clause EXECUTE AS. L'utilisateur exécutant le module est, en effet, usurper l'identité de l'utilisateur spécifié.
Le contexte spécifié dans la clause EXECUTE AS du module est valide seulement pour la durée de l'exécution du module. Le contexte revient au appelant lorsque l'exécution du module est terminée.
Les éléments suivants doivent être créés par un utilisateur disposant des autorisations nécessaires pour interroger les DMV.
CREATE PROCEDURE MyStoredProcedure
WITH EXECUTE AS OWNER
AS
BEGIN
SET NOCOUNT ON
SELECT TOP 1
FROM tb
INNER JOIN sys.dm_exec_connections cn
ON tb.client_net_address = cn.client_net_address
WHERE cn.Session_Id = @@SPID
END
Ensuite, vous devrez donner aux utilisateurs les autorisations nécessaires pour exécuter la procédure stockée:
Mettre à jour pour créer les autorisations adéquates
Vous devrez définir votre base de données sur Trustworthy (voir Définir la base de données sur Trustworthy :
ALTER DATABASE MyDataBase SET TRUSTWORTHY ON
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
CREATE USER [user_mortal_jack] FOR LOGIN [user_mortal_jack] WITH DEFAULT_SCHEMA=[dbo]
GO
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
J'ai testé cela et cela fonctionne maintenant comme prévu
Vous pouvez utiliser les connexions DMV pour y parvenir.
select ec.client_net_address,* from sys.dm_exec_connections ec
join
sys.dm_exec_requests rq
on rq.connection_id=ec.connection_id
cross apply
sys.dm_exec_sql_text(rq.sql_handle) txt
where txt.text like '%your stored proc%'
MSDN pour client_net_address
Adresse d'hôte du client se connectant à ce serveur. Est nullable.
Pour obtenir l'adresse IP et le nom d'utilisateur d'un appelant sans lui accorder des autorisations spéciales, vous pouvez tricher le serveur et la base de données un peu. Deux choses sont nécessaires pour y parvenir:
ALTER DATABASE MyDataBase SET TRUSTWORTHY ON
[user_mortal_jack]
) dans mon exemple [user_immortan_joe]
[user_immortan_joe]
dans MyDataBasemaster
grant VIEW SERVER STATE to [user_immortan_joe];
MyDataBase
, créez une procédure stockée (et non pas MyStoredProcedure
, dans mon exemple get_ip
) qui reçoit un int représentant un paramètre session_id
spécifique output
(sortie, pas retour) l'adresse IP ou session_id
. Créez-le with execute as 'user_immortan_joe'
.get_ip
et de SUSER_SNAME()
, l'adresse IP et le nom d'utilisateur de l'appelant soient renvoyés.De cette façon, vous obtenez l'adresse IP et le nom d'utilisateur de tout appelant de MyStoredProcedure
en respectant le principe du moindre privilège et en évitant les problèmes que vous avez rencontrés lors de la recherche d'une solution.
Exemple de script:
use MyDataBase
go
alter database MyDataBase set trustworthy on;
go
CREATE LOGIN [user_mortal_jack] WITH PASSWORD=N'LongYouLive!!!';
go
create user [user_mortal_jack];
go
CREATE LOGIN [user_immortan_joe] WITH PASSWORD=N'ToTheGatesOfValhalla!!!';
go
create user [user_immortan_joe];
go
use master
go
grant VIEW SERVER STATE to [user_immortan_joe];
use MyDataBase
go
create PROCEDURE get_ip
@spid int, @ip varchar(50) output
with execute as 'user_immortan_joe'
as
begin
select @ip = client_net_address
from sys.dm_exec_connections
where session_id = @spid
end;
go
create procedure MyStoredProcedure
as
begin
declare @spid int = @@spid, @ip varchar(50);
exec dbo.get_ip @spid,@ip output;
select @ip as ipAddress ,SUSER_SNAME() as userName
end
go
GRANT EXECUTE ON MyStoredProcedure TO [user_mortal_jack];
go
EXECUTE AS USER = 'user_mortal_jack'
exec MyStoredProcedure
REVERT