TSQL - 执行CLR权限
我从 CLR(.net 程序集)获得了一个 sql 过程,执行时返回错误
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()
这是我的 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
,这是我的类(程序集)
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();
}
}
}
I got a sql procedure from a CLR (.net Assembly) that when executed returns an error
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()
This is my SQL script
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
and this is my Class (Assembly)
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();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题很简单,您正在尝试访问程序集中标记为“SAFE”的外部资源。访问外部资源需要将程序集设置为至少
EXTERNAL_ACCESS
(在某些情况下UNSAFE
)。但是,查看您的代码,您只是尝试连接到本地实例,在这种情况下,有一种更简单(更快)的方法可以实现此目的:使用"Context Connection = true;"
作为连接字符串。上下文连接是与当前进程/会话的直接连接,有时也称为进程内连接。使用上下文连接的好处是:
SAFE
的程序集中完成#
开头的访问) > 而不是双##
)SET CONTEXT_INFO
和CONTEXT_INFO()
另外:
SqlClientPermission
正式请求权限,Dispose()
方法来清理外部资源。并非所有对象都具有此功能,但SqlConnection
、SqlCommand
和SqlDataReader
肯定具有。人们通常将一次性对象包装在using()
块中,因为它是一个编译器宏,扩展为调用Dispose()
方法的 try/finally 结构在finally
中确保即使发生错误,它也会被调用。Dispose()
方法会自动处理对Close()
的调用,因此您通常不需要调用Close()
> 明确地。您的代码应如下所示:
The problem is simply that you are attempting to access an external resource in an Assembly that is marked as
SAFE
. Accessing external resources requires setting the Assembly to at leastEXTERNAL_ACCESS
(and in some casesUNSAFE
). However, looking at your code, you are simply trying to connect to the local instance, and in that case there is a far easier (and faster) means of doing this: using"Context Connection = true;"
as the ConnectionString.The Context Connection is a direct connection to the current process / session, and it is sometimes referred to as the in-process connection. The benefits of using the Context Connection are:
SAFE
#
instead of double##
)SET CONTEXT_INFO
andCONTEXT_INFO()
Also:
SqlClientPermission
Dispose()
method. Not all objects have this, butSqlConnection
,SqlCommand
, andSqlDataReader
certainly do. It is typical for people to wrap disposable objects in ausing()
block as it is a compiler macro that expands to a try / finally structure that calls theDispose()
method in thefinally
to ensure that it is called, even if an error occurs.Dispose()
method of many / most disposable objects automatically handles the call toClose()
so you usually do not need to callClose()
explicitly.Your code should look as follows:
我只是想在此添加我的两种感觉。我正在做一些非常相似的事情,但我遇到了同样的错误。这是我发现的,但是 b/c 我没有这种级别的数据库访问权限,我无法测试它。
完整帖子在此。 ..
I just wanted to add my two sense to this. I'm doing something very similiar and I'm getting the same error. Here is what I found, however b/c I don't have this level of access to the DB I can't test it.
Full Post Here...
您是否已将 DB 设置为 Trustworth ON 并启用了 clr?
试试这个
我有一个指南这里如何使用 CLR 存储过程可能会有所帮助。
Have you set your DB set to Trusrtworth ON and enabled clr?
Try this
I have a guide here on how to use CLR Stored Procedures that might help.