我正在尝试使用 IBM 提供的 .NET 核心库的 alpha 版本连接到 AS400 上的 DB2 数据库,而我的项目是用 .NET 8 编写的。
由于我有多个服务器要连接,因此它们在某处配置,并且我使用代码动态创建连接字符串:
iDB2ConnectionStringBuilder builder = new()
{
DataSource = "[ServerAddress]",
UserID = "[User]",
Password = "[Password]",
PersistSecurityInfo = true
};
然后我使用
builder.ConnectionString
打开连接。
当我在生产环境中发布此代码时,出现以下错误:
System.TypeInitializationException: The type initializer for 'Alfa.Data.DB2.iSeries.iDB2Trace' threw an exception.
---> System.UnauthorizedAccessException: Access to the path 'CWB_MP_TI_EVENT' is denied.
at System.Threading.EventWaitHandle.CreateEventCore(Boolean initialState, EventResetMode mode, String name, Boolean& createdNew)
at Alfa.Data.DB2.iSeries.iDB2NamedEvent..ctor(String eventName)
at Alfa.Data.DB2.iSeries.iDB2Trace..cctor()
--- End of inner exception stack trace ---
at Alfa.Data.DB2.iSeries.iDB2Trace.get_Tracing()
at Alfa.Data.DB2.iSeries.iDB2ConnectionStringBuilder..ctor()
异常是由
iDB2NamedEvent
的构造函数引发的,iDB2Trace
又被 iDB2ConnectionStringBuilder
调用,所以显然我用来实际打开连接的代码都没有被调用。
我对dll进行了逆向工程,找到了抛出异常的方法的代码,即:
internal iDB2NamedEvent(string eventName)
{
SecurityPermission securityPermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
waitHandle = null;
string identity = (new SecurityIdentifier(WellKnownSidType.WorldSid, null).Translate(typeof(NTAccount)) as NTAccount).ToString();
try
{
securityPermission.Assert();
EventWaitHandleSecurity eventWaitHandleSecurity = new EventWaitHandleSecurity();
EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(identity, EventWaitHandleRights.FullControl, AccessControlType.Allow);
eventWaitHandleSecurity.AddAccessRule(rule);
waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "CWB_MP_TI_EVENT", out var _);
}
catch
{
CodeAccessPermission.RevertAssert();
throw;
}
CodeAccessPermission.RevertAssert();
}
此代码在 Windows 服务和 IIS 中的某些 ASP.NET Web 服务中运行。现在为了使其工作,我必须在这两种情况下将他们运行的用户设置为
Local System
。如果我使用任何不同的用户,我会收到错误。
我已经谷歌搜索了两天,但没有找到任何可以帮助的东西,任何想法将不胜感激。
错误的根本原因在于与创建或访问命名事件相关的权限限制。特别是,CWB_MP_TI_EVENT 受到强制提升权限的安全策略的约束。当应用程序在与本地系统不同的用户上下文下运行时,可能不存在必要的权限,从而触发 UnauthorizedAccessException。
1。确保用户帐户具有必要的权限 要解决此问题,您可以:
为运行该服务的用户帐户授予必要的权限,以便其正常工作:
2。修改代码中的安全设置
如果您可以控制代码,则可以通过编程方式修改安全设置,以授予对事件句柄的适当访问权限。以下是如何修改 iDB2NamedEvent 方法以确保使用适当的安全设置创建事件句柄的示例:
internal iDB2NamedEvent(string eventName)
{
SecurityPermission securityPermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
waitHandle = null;
string identity = (new SecurityIdentifier(WellKnownSidType.WorldSid, null).Translate(typeof(NTAccount)) as NTAccount).ToString();
try
{
securityPermission.Assert();
EventWaitHandleSecurity eventWaitHandleSecurity = new EventWaitHandleSecurity();
EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(identity, EventWaitHandleRights.FullControl, AccessControlType.Allow);
eventWaitHandleSecurity.AddAccessRule(rule);
bool createdNew;
waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "CWB_MP_TI_EVENT", out createdNew, eventWaitHandleSecurity);
}
catch
{
CodeAccessPermission.RevertAssert();
throw;
}
CodeAccessPermission.RevertAssert();
}
3.在 IIS 中使用应用程序池身份 对于 IIS,请确保应用程序池标识具有必要的权限:
打开 IIS 管理器。
选择运行 ASP.NET 应用程序的应用程序池。
单击“高级设置...”。
在“流程模型”下,将“身份”更改为具有所需权限的帐户,或将其配置为使用您确保具有这些权限的自定义帐户。
4。作为本地系统运行 作为最后的手段,如果更改权限不可行,您可以继续在本地系统帐户下运行服务。但是,出于安全原因,通常不建议在本地系统下运行服务,除非绝对必要。
如果您仍然遇到任何错误,请告诉我。