.NET Core 抛出 WindowsCryptographicException:访问在 X509Store.Add 上被拒绝
.NET Core throws WindowsCryptographicException: Access is denied on X509Store.Add
我写了一个安装证书的方法:
public void Install(StoreName storeName, StoreLocation storeLocation)
{
using var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
}
并通过传递 StoreName.Root、StoreLocation.CurrentUser
来调用它
certificateManager.Install(StoreName.Root, StoreLocation.CurrentUser);
将导致:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied.
at Internal.Cryptography.Pal.StorePal.Add(ICertificatePal certificate)
at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)
at Pixeval.Persisting.WebApi.CertificateManager.Install(StoreName storeName, StoreLocation storeLocation) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\Persisting\WebApi\CertificateManager.cs:line 99
at Pixeval.App.InstallFakeCaCertificate() in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 129
at Pixeval.App.OnStartup(StartupEventArgs e) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 68
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at Pixeval.App.Main()
谷歌搜索后,我发现大多数相关问题都在询问 StoreLocation.LocalMachine,我没有在 StoreLocation.CurrentUser
找到安装证书的任何解决方案
注意:我无法重现此问题,因为它是由我的应用程序的一位用户发布的
有两个问题,一个与配置有关,另一个与代码本身有关。
问题 1:
引发异常是因为 CurrentUser.Root
存储是只读的。您的系统管理员似乎配置了 GPO 以限制用户写入此存储:
问题 2:
即使您修复了此问题,代码也可能以不同的方式失败:它可能 hang/freeze。这是因为当您将证书安装到 CurrentUser.Root
时,将调用弹出窗口(您无法避免此弹出窗口)以确认操作:
我没有测试过,但是如果在后台线程中调用代码,那么代码可能会失败,因为 UI 线程是从后台线程访问的。
如果应用程序作为 service/batch/imersonated 上下文运行(例如网络应用程序),弹出窗口将显示在单独的会话中,而不是在主屏幕上,因此没有人能够按确认按钮。
因此,您不得在 CurrentUser.Root
当前交互式记录的用户上下文之外安装证书,并确保任何人都可以按下确认按钮。并避免从背景任务中执行此代码。
我写了一个安装证书的方法:
public void Install(StoreName storeName, StoreLocation storeLocation)
{
using var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
}
并通过传递 StoreName.Root、StoreLocation.CurrentUser
来调用它certificateManager.Install(StoreName.Root, StoreLocation.CurrentUser);
将导致:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied.
at Internal.Cryptography.Pal.StorePal.Add(ICertificatePal certificate)
at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)
at Pixeval.Persisting.WebApi.CertificateManager.Install(StoreName storeName, StoreLocation storeLocation) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\Persisting\WebApi\CertificateManager.cs:line 99
at Pixeval.App.InstallFakeCaCertificate() in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 129
at Pixeval.App.OnStartup(StartupEventArgs e) in C:\NotSystem\Coding\projects\visualstudio\csharp\Pixeval\App.xaml.cs:line 68
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at Pixeval.App.Main()
谷歌搜索后,我发现大多数相关问题都在询问 StoreLocation.LocalMachine,我没有在 StoreLocation.CurrentUser
找到安装证书的任何解决方案注意:我无法重现此问题,因为它是由我的应用程序的一位用户发布的
有两个问题,一个与配置有关,另一个与代码本身有关。
问题 1:
引发异常是因为 CurrentUser.Root
存储是只读的。您的系统管理员似乎配置了 GPO 以限制用户写入此存储:
问题 2:
即使您修复了此问题,代码也可能以不同的方式失败:它可能 hang/freeze。这是因为当您将证书安装到 CurrentUser.Root
时,将调用弹出窗口(您无法避免此弹出窗口)以确认操作:
我没有测试过,但是如果在后台线程中调用代码,那么代码可能会失败,因为 UI 线程是从后台线程访问的。
如果应用程序作为 service/batch/imersonated 上下文运行(例如网络应用程序),弹出窗口将显示在单独的会话中,而不是在主屏幕上,因此没有人能够按确认按钮。
因此,您不得在 CurrentUser.Root
当前交互式记录的用户上下文之外安装证书,并确保任何人都可以按下确认按钮。并避免从背景任务中执行此代码。