CLR 函数中的反序列化失败
Deserialization in a CLR Function fails
我用C#写了一些文字的音标转换的例程。这些例程需要一堆 aof 定义的转换规则 (search-string/replace-string)。这个想法是将这些规则存储为程序集中的嵌入式资源,然后从中读取规则。反序列化的起点如下
public static phonet42n.Core.Rules Deserialize(phonet42n.Core.Rules.Ressources ressource)
{
string ressourceName;
phonet42n.Core.Rules returnValue;
System.Xml.XmlReader reader;
System.Xml.Serialization.XmlSerializer xmlSerializer;
phonet42n.Core.SerializableRules serializeableRules;
returnValue = new phonet42n.Core.Rules();
switch (ressource)
{
case Ressources.German_01:
ressourceName = RESSOURCE_XML_GERMAN_01;
break;
case Ressources.German_02:
ressourceName = RESSOURCE_XML_GERMAN_02;
break;
default:
ressourceName = RESSOURCE_XML_GERMAN_01;
break;
}
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ressourceName))
{
using (reader = System.Xml.XmlReader.Create(stream))
{
xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(phonet42n.Core.SerializableRules));
serializeableRules = (phonet42n.Core.SerializableRules)xmlSerializer.Deserialize(reader);
}
}
foreach (phonet42n.Core.Rule entry in serializeableRules.Rules)
{
if (entry.SearchString != null && entry.SearchString.Length > 0)
{
returnValue.Add(entry.Index, entry);
}
}
return returnValue;
}
应用程序在常规可执行文件中运行正常。
在 SQL 服务器中执行注册函数时出现以下错误:
SELECT [dbo].[Phonet42n]('mayer', 1)
产生...
Meldung 6522, Ebene 16, Status 1, Zeile 22
.NET Framework-Fehler beim Ausführen der benutzerdefinierten Routine oder des benutzerdefinierten Aggregats 'Phonet42n':
System.InvalidOperationException: Fehler im XML-Dokument (3,4). ---> System.MethodAccessException: Fehler beim Versuch der Methode "Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read8_SerializableRules(Boolean, Boolean)", auf Methode "phonet42n.Core.Rule..ctor()" zuzugreifen.
System.MethodAccessException:
bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read8_SerializableRules(Boolean isNullable, Boolean checkType)
bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read19_Rules()
System.InvalidOperationException:
bei System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
bei System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
bei phonet42n.Core.Rules.Deserialize(Ressources ressource)
bei phonet42n.Core.Rules..ctor(Ressources ressource, Characters characters)
bei phonet42n.Core.HashTable..ctor(Ressources ressource)
bei phonet42n.Core.Match..ctor(Re...
有什么想法吗?
每当出现安全异常时,您可以先尝试将 Assembly 设置为 PERMISSION_SET = EXTERNAL_ACCESS
,如果这不起作用,您可以尝试 UNSAFE
。但是,如果有人试图动态加载程序集,那么即使对于标记为 UNSAFE
.
的程序集,也应该禁止这样做
由于这里的问题是想要包含一套规则,这可能会在另一个大会上完成。然后主程序集可以引用包含规则的程序集,您只需先将包含规则的程序集加载到 SQL 服务器即可。这将允许两个程序集保持标记为 SAFE
.
当然,如果没有迫切需要将规则分开,那么您也可以将它们直接放入Class中的集合中。
除了构造函数部分 (private/public),我对所有内容都进行了撤消。无论是否签署程序集,我都会收到以下消息 (10327):
CREATE ASSEMBLY for assembly 'phonet42n.Core' failed because assembly
'phonet42n.Core' is not authorized for PERMISSION_SET =
EXTERNAL_ACCESS. The assembly is authorized when either of the
following is true: the database owner (DBO) has EXTERNAL ACCESS
ASSEMBLY permission and the database has the TRUSTWORTHY database
property on; or the assembly is signed with a certificate or an
asymmetric key that has a corresponding login with EXTERNAL ACCESS
ASSEMBLY permission.
不幸的是,我不熟悉签署程序集:我只是选中了项目属性 属性 页面中的复选框:
不知道是否缺少额外的步骤。
无论如何,按照消息中的建议,我尝试使用以下语句创建非对称密钥:
USE master;
GO
IF EXISTS (SELECT * FROM [sys].[syslogins] WHERE [sid] = SUSER_SID('SQLCLRTestLogin'))
BEGIN
PRINT 'Dropping Login...'
DROP LOGIN [SQLCLRTestLogin]
PRINT 'End'
END
GO
IF EXISTS (SELECT * FROM [sys].[asymmetric_keys] WHERE [name] = 'SQLCLRTestKey')
BEGIN
PRINT 'Dropping Asymmetric Key...'
DROP ASYMMETRIC KEY [SQLCLRTestKey]
PRINT 'End'
END
GO
BEGIN
PRINT 'Creating Login...'
CREATE ASYMMETRIC KEY [SQLCLRTestKey] FROM EXECUTABLE FILE = 'D:\phonet42n.net\Core\bin\Debug\phonet42n.Core.dll'
PRINT 'End'
PRINT 'Creating Asymmetric Key...'
CREATE LOGIN [SQLCLRTestLogin] FROM ASYMMETRIC KEY [SQLCLRTestKey]
PRINT 'End'
PRINT 'Granting Access...'
GRANT EXTERNAL ACCESS ASSEMBLY TO [SQLCLRTestLogin];
PRINT 'End'
END
GO
如果是已签名程序集,这些语句会成功,而如果是未签名程序集,我会收到以下错误消息 (15208 ):
The certificate, asymmetric key, or private key file does not exist or
has invalid format.
顺便说一句..不知道这是否重要。程序集的目标 .NET Framework aof 是 4.5。最后...来到初始错误消息: Adwaenyth 是正确的缺少 public 默认构造函数。该消息到目前为止具有误导性,因为缺少的构造函数不会影响程序集的注册。只有在运行时成功注册后调用函数 phonet42n 时,您才会收到消息。
我真的不知道,这是否是设计使然的解决方案。而且我不知道我是否为任何潜在线程打开了大门。
我只能强调 Stairway series articles 尤其是在 SQLCLR 上。出色的!它有助于了解 SQLCLR 的工作原理及其用途。
最后(真的):我的总体结果是,我将从 XML 中提取规则并按照 srutzky 的建议通过填充集合直接加载它们。可能会更高效。
我用C#写了一些文字的音标转换的例程。这些例程需要一堆 aof 定义的转换规则 (search-string/replace-string)。这个想法是将这些规则存储为程序集中的嵌入式资源,然后从中读取规则。反序列化的起点如下
public static phonet42n.Core.Rules Deserialize(phonet42n.Core.Rules.Ressources ressource)
{
string ressourceName;
phonet42n.Core.Rules returnValue;
System.Xml.XmlReader reader;
System.Xml.Serialization.XmlSerializer xmlSerializer;
phonet42n.Core.SerializableRules serializeableRules;
returnValue = new phonet42n.Core.Rules();
switch (ressource)
{
case Ressources.German_01:
ressourceName = RESSOURCE_XML_GERMAN_01;
break;
case Ressources.German_02:
ressourceName = RESSOURCE_XML_GERMAN_02;
break;
default:
ressourceName = RESSOURCE_XML_GERMAN_01;
break;
}
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ressourceName))
{
using (reader = System.Xml.XmlReader.Create(stream))
{
xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(phonet42n.Core.SerializableRules));
serializeableRules = (phonet42n.Core.SerializableRules)xmlSerializer.Deserialize(reader);
}
}
foreach (phonet42n.Core.Rule entry in serializeableRules.Rules)
{
if (entry.SearchString != null && entry.SearchString.Length > 0)
{
returnValue.Add(entry.Index, entry);
}
}
return returnValue;
}
应用程序在常规可执行文件中运行正常。
在 SQL 服务器中执行注册函数时出现以下错误:
SELECT [dbo].[Phonet42n]('mayer', 1)
产生...
Meldung 6522, Ebene 16, Status 1, Zeile 22
.NET Framework-Fehler beim Ausführen der benutzerdefinierten Routine oder des benutzerdefinierten Aggregats 'Phonet42n':
System.InvalidOperationException: Fehler im XML-Dokument (3,4). ---> System.MethodAccessException: Fehler beim Versuch der Methode "Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read8_SerializableRules(Boolean, Boolean)", auf Methode "phonet42n.Core.Rule..ctor()" zuzugreifen.
System.MethodAccessException:
bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read8_SerializableRules(Boolean isNullable, Boolean checkType)
bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read19_Rules()
System.InvalidOperationException:
bei System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
bei System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
bei phonet42n.Core.Rules.Deserialize(Ressources ressource)
bei phonet42n.Core.Rules..ctor(Ressources ressource, Characters characters)
bei phonet42n.Core.HashTable..ctor(Ressources ressource)
bei phonet42n.Core.Match..ctor(Re...
有什么想法吗?
每当出现安全异常时,您可以先尝试将 Assembly 设置为 PERMISSION_SET = EXTERNAL_ACCESS
,如果这不起作用,您可以尝试 UNSAFE
。但是,如果有人试图动态加载程序集,那么即使对于标记为 UNSAFE
.
由于这里的问题是想要包含一套规则,这可能会在另一个大会上完成。然后主程序集可以引用包含规则的程序集,您只需先将包含规则的程序集加载到 SQL 服务器即可。这将允许两个程序集保持标记为 SAFE
.
当然,如果没有迫切需要将规则分开,那么您也可以将它们直接放入Class中的集合中。
除了构造函数部分 (private/public),我对所有内容都进行了撤消。无论是否签署程序集,我都会收到以下消息 (10327):
CREATE ASSEMBLY for assembly 'phonet42n.Core' failed because assembly 'phonet42n.Core' is not authorized for PERMISSION_SET = EXTERNAL_ACCESS. The assembly is authorized when either of the following is true: the database owner (DBO) has EXTERNAL ACCESS ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with EXTERNAL ACCESS ASSEMBLY permission.
不幸的是,我不熟悉签署程序集:我只是选中了项目属性 属性 页面中的复选框:
不知道是否缺少额外的步骤。
无论如何,按照消息中的建议,我尝试使用以下语句创建非对称密钥:
USE master;
GO
IF EXISTS (SELECT * FROM [sys].[syslogins] WHERE [sid] = SUSER_SID('SQLCLRTestLogin'))
BEGIN
PRINT 'Dropping Login...'
DROP LOGIN [SQLCLRTestLogin]
PRINT 'End'
END
GO
IF EXISTS (SELECT * FROM [sys].[asymmetric_keys] WHERE [name] = 'SQLCLRTestKey')
BEGIN
PRINT 'Dropping Asymmetric Key...'
DROP ASYMMETRIC KEY [SQLCLRTestKey]
PRINT 'End'
END
GO
BEGIN
PRINT 'Creating Login...'
CREATE ASYMMETRIC KEY [SQLCLRTestKey] FROM EXECUTABLE FILE = 'D:\phonet42n.net\Core\bin\Debug\phonet42n.Core.dll'
PRINT 'End'
PRINT 'Creating Asymmetric Key...'
CREATE LOGIN [SQLCLRTestLogin] FROM ASYMMETRIC KEY [SQLCLRTestKey]
PRINT 'End'
PRINT 'Granting Access...'
GRANT EXTERNAL ACCESS ASSEMBLY TO [SQLCLRTestLogin];
PRINT 'End'
END
GO
如果是已签名程序集,这些语句会成功,而如果是未签名程序集,我会收到以下错误消息 (15208 ):
The certificate, asymmetric key, or private key file does not exist or has invalid format.
顺便说一句..不知道这是否重要。程序集的目标 .NET Framework aof 是 4.5。最后...来到初始错误消息: Adwaenyth 是正确的缺少 public 默认构造函数。该消息到目前为止具有误导性,因为缺少的构造函数不会影响程序集的注册。只有在运行时成功注册后调用函数 phonet42n 时,您才会收到消息。
我真的不知道,这是否是设计使然的解决方案。而且我不知道我是否为任何潜在线程打开了大门。
我只能强调 Stairway series articles 尤其是在 SQLCLR 上。出色的!它有助于了解 SQLCLR 的工作原理及其用途。
最后(真的):我的总体结果是,我将从 XML 中提取规则并按照 srutzky 的建议通过填充集合直接加载它们。可能会更高效。