2010-11-05 7 views
4

Je suis une procédure SQL à partir d'un CLR (.net Assemblée) que lors du retour exécuté une erreurTSQL - CLR exécution Permission

Msg 6522, Level 16, State 1, Procedure sp_HelloWorld, Line 0 
A .NET Framework error occurred during execution of user defined routine or aggregate 'sp_HelloWorld': 
System.Security.SecurityException: Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed. 
System.Security.SecurityException: 
    at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) 
    at System.Security.PermissionSet.Demand() 
    at System.Data.Common.DbConnectionOptions.DemandPermission() 
    at System.Data.SqlClient.SqlConnection.PermissionDemand() 
    at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) 
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 
    at System.Data.SqlClient.SqlConnection.Open() 
    at HelloWorld.SQLCLR.HelloWorld() 

Ceci est mon script SQL

go 
drop procedure HelloWorld 
drop assembly HelloWorld 
GO 

create assembly HelloWorld from 'F:\HelloWorld.dll' 
with permission_set = safe 
Go 
create procedure sp_HelloWorld 
as external name HelloWorld.[HelloWorld.SQLCLR].HelloWorld 
go 
exec sp_HelloWorld 

et voici mon Classe (Assemblage)

using Microsoft.SqlServer.Server; 
using System.Data.SqlTypes; 
using System.Data.SqlClient; 
using System.Security.Permissions; 
using System.Data; 

namespace HelloWorld 
{ 
    public class SQLCLR 
    { 
     [Microsoft.SqlServer.Server.SqlProcedure] 
     public static void HelloWorld() 
     { 
      string connectString1 = @"Data Source=localhost;Initial Catalog=ItemData;Integrated Security=True"; 

      SqlClientPermission permission = new SqlClientPermission(PermissionState.None); 
      permission.Add(connectString1, "", KeyRestrictionBehavior.AllowOnly); 
      permission.PermitOnly(); 
      SqlConnection sqlcon = new SqlConnection(connectString1); 
      sqlcon.Open(); 
      SqlCommand sqlcmd = new SqlCommand("SELECT Top 1 * FROM ItemData.dbo.Item", sqlcon); 
      SqlDataReader reader = sqlcmd.ExecuteReader(); 
      SqlContext.Pipe.Send(reader); 
      sqlcon.Close(); 
     } 
    } 
} 
+0

Juvil, si vous êtes toujours intéressé, j'ai ajouté une [réponse] (http://stackoverflow.com/a/32341040/577765) que explique le problème et corrige le code des meilleures pratiques. J'ai également expliqué pourquoi les autres réponses ne fonctionnent pas (dans les commentaires sur ces réponses). –

Répondre

-3

Avez-vous défini votre groupe de base de données sur Trusrtworth ON et activé clr?

Essayez cette

sp_configure 'clr enabled', 1 
GO 
RECONFIGURE 
GO 

ALTER DATABASE [YourDatabase] SET TRUSTWORTHY ON 
GO 

J'ai un guide here sur la façon d'utiliser les procédures stockées CLR qui pourraient aider.

+0

Cela n'a pas aidé à résoudre le problème pour moi. – Ryan

+0

@Ryan et Raymund: ces étapes n'aideront pas. Si CLR n'était pas déjà activé, tenter d'exécuter un code SQLCLR entraînerait une erreur indiquant que l'intégration CLR n'a pas été activée. La définition de la base de données sur TRUSTWORTHY ON, bien que rapide et facile, et généralement utile pour les assemblages EXTERNAL_ACCESS ou UNSAFE, est généralement inutile car elle présente un risque de sécurité. Le problème ici est que l'assembly est défini sur SAFE, ce qui interdit toute demande externe. L'étape 1 consisterait à définir l'assemblage sur EXTERNAL_ACCESS, mais il existe une option encore meilleure, comme je l'ai montré dans ma [réponse] (http://stackoverflow.com/a/32341040/577765). –

+0

Je suis d'accord que ce n'est pas vraiment sur le point. Le problème est les autorisations. L'autre commentaire et l'autre réponse vont au coeur du problème. –

0

Je voulais juste ajouter mes deux sens à cela. Je fais quelque chose de très similaire et je reçois la même erreur. Voici ce que j'ai trouvé, mais b/c je n'ai pas ce niveau d'accès à la DB je ne peux pas le tester.

facile (mais pas MSDN recommandé juste jet un proc CLR pour exécuter) est de définir le niveau d'autorisation à external_access ...

Politique hôte SQL Server Niveau autorisation Définit le jeu d'accès au code Les autorisations de sécurité accordées aux assemblys par le niveau d'accès de l'hôte SQL Server sont déterminées par le jeu d'autorisations spécifié lorsque créant l'assembly. Il existe trois jeux d'autorisations: SAFE, EXTERNAL_ACCESS et UNSAFE.

Le niveau de permision est situé sur les pages de propriétés du projet CLR , onglet de base de données - définir des autorisations de niveau externe, définissez Aassembly propriétaire-dbo et exécutez tsql ALTER DATABASE DataBaseName SET TRUSTWORTHY SUR 'Cela se le travail FAIT! - et le SmtpClient wiill fonctionne ok ... puis faites-le droit et signer le Assenbly avec un nom fort fichier clé ...

Full Post Here...

+1

Étant donné que le désir est de se connecter à l'instance locale, ce n'est certainement pas l'approche la plus simple ou la meilleure. Et définir la base de données sur TRUSTWORTHY ON, tout en étant rapide et facile, est une mauvaise approche qui est généralement inutile. Il est vrai que la dernière phrase dit "alors faites-le bien ...", mais si quelqu'un l'utilise avec "TRUSTWORTHY ON", il y a très peu de chance qu'il revienne le faire plus tard. De toute façon, j'explique le vrai problème dans ma [réponse] (http://stackoverflow.com/a/32341040/577765). –

5

Le problème est simplement que vous tentez d'accéder à un ressource externe dans un assembly marqué SAFE. Pour accéder aux ressources externes, vous devez configurer l'assemblage sur au moins EXTERNAL_ACCESS (et dans certains cas UNSAFE). Cependant, en regardant votre code, vous essayez simplement de vous connecter à l'instance locale, et dans ce cas, il y a un moyen beaucoup plus facile (et plus rapide) de le faire: utiliser "Context Connection = true;" comme ConnectionString.

La connexion de contexte est une connexion directe au processus/à la session en cours, et elle est parfois appelée connexion en cours de processus.Les avantages de l'utilisation de la connexion de contexte sont:

  • peut être fait dans les assemblées marquées comme SAFE
  • accès aux objets temporaires locaux (tables temporaires et procédures temporaires, à la fois avec des noms commençant par un seul # au lieu de deux ##)
  • accès à SET CONTEXT_INFO et CONTEXT_INFO()
  • pas de démarrage de connexion au-dessus

également:

  • si vous utilisez vous n'avez pas besoin de demander officiellement en cours, Connexion contexte ou une connexion régulière/externe, l'autorisation à l'aide SqlClientPermission
  • vous devriez toujours nettoyer les ressources externes en appelant leur Dispose() méthode. Tous les objets n'ont pas cela, mais SqlConnection, SqlCommand, et SqlDataReader le font certainement. Il est courant que des personnes enveloppent des objets jetables dans un bloc using() car c'est une macro de compilateur qui se développe en une structure try/finally qui appelle la méthode Dispose() dans le finally pour s'assurer qu'elle est appelée, même en cas d'erreur.
  • La méthode Dispose() de beaucoup/la plupart des objets jetables gère automatiquement l'appel à Close() de sorte que vous n'avez généralement pas besoin d'appeler Close() explicitement.

Votre code devrait se présenter comme suit:

[Microsoft.SqlServer.Server.SqlProcedure] 
public static void HelloWorld() 
{ 
    using (SqlConnection sqlcon = new SqlConnection("Context Connection = true;") 
    { 
    using (SqlCommand sqlcmd = new SqlCommand("SELECT Top 1 * FROM ItemData.dbo.Item", 
       sqlcon)) 
    { 
     sqlcon.Open(); 

     using (SqlDataReader reader = sqlcmd.ExecuteReader()) 
     { 
     SqlContext.Pipe.Send(reader); 
     } 
    } 
    } 
} 
+0

Bonne info ... ça a tellement de sens d'avoir ça. Mais! Une chose de plus importante dont nous avons besoin ... test pour where-are-we-running pour choisir entre ceci et une chaîne typique afin que nous puissions utiliser la chaîne de connexion typique au moment du design. Comment testons-nous si nous avons ce "contexte serveur sql"? –

+0

Juste trouvé exactement la réponse ... également écrit par vous :). Peut-être que vous pourriez ajouter le lien ... https://stackoverflow.com/a/31279625/1518460 –