如何在Acumatica框架中通过网络凭据认证创建共享路径文件
Got it, let's walk through how to implement creating files in an authenticated network share within the Acumatica framework. This involves handling credentials securely and working within Acumatica's runtime context to avoid permission issues, since the application pool identity typically won't have access to restricted network shares.
We'll use a combination of:
- Acumatica's Secure Storage to store network credentials (no hardcoding!)
- .NET user impersonation to temporarily run code under the network user's identity
- Standard .NET file operations wrapped in Acumatica's error handling
First, add your network share credentials to Acumatica's Secure Storage (found under System > Management > Secure Storage). Create a new credential entry with a key like NetworkShare_Creds (you'll reference this key in code).
We'll use P/Invoke calls to LogonUser to get a user token, then impersonate that user. Add this helper method to your custom Acumatica code (e.g., a BLC extension or action):
using System; using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Security.Principal; using PX.Data; public class NetworkShareHelper { // P/Invoke declarations for Windows authentication [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); /// <summary> /// Impersonates a network user to access restricted resources /// </summary> public static WindowsImpersonationContext ImpersonateNetworkUser(PXSecureStorage.Credentials creds) { if (creds == null) throw new PXException("Network credentials not found."); IntPtr tokenHandle = IntPtr.Zero; try { // Use LOGON32_LOGON_NEW_CREDENTIALS for network access bool logonSuccess = LogonUser( creds.UserName, creds.Domain, creds.Password, 9, // LOGON32_LOGON_NEW_CREDENTIALS 0, // LOGON32_PROVIDER_DEFAULT out tokenHandle); if (!logonSuccess) { throw new Win32Exception(Marshal.GetLastWin32Error()); } WindowsIdentity userIdentity = new WindowsIdentity(tokenHandle); return userIdentity.Impersonate(); } catch { if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); throw; } } }
Now, in your custom action or event handler, retrieve the credentials, impersonate the user, and create the file. Here's an example using a button action in a BLC:
public class MyGraphExtension : PXGraphExtension<MyBaseGraph> { public PXAction<MyDAC> CreateFileInShare; [PXButton(CommitChanges = true)] [PXUIField(DisplayName = "Create File in Network Share")] public void createFileInShare() { // Ensure the user has permission to perform this action PXAccess.EnsurePermission<MyCustomPermission>(); // Retrieve credentials from Secure Storage var networkCreds = PXSecureStorage.GetCredentials("NetworkShare_Creds"); if (networkCreds == null) { throw new PXSetPropertyException("Network share credentials are not configured in Secure Storage.", PXErrorLevel.Error); } using (var impersonationContext = NetworkShareHelper.ImpersonateNetworkUser(networkCreds)) { if (impersonationContext == null) { throw new PXException("Failed to impersonate the network user."); } try { // Define your network share path string networkPath = @"\\fileserver\shared\AcumaticaGeneratedFile.txt"; // Create and write to the file using (StreamWriter writer = File.CreateText(networkPath)) { writer.WriteLine($"File created at {DateTime.Now:yyyy-MM-dd HH:mm:ss} from Acumatica."); } PXTrace.WriteInformation("Successfully created file at: {0}", networkPath); PXUIFieldAttribute.SetError<MyDAC.note>(Base.Caches[typeof(MyDAC)], null, "File created successfully!"); } catch (Exception ex) { // Throw user-friendly error within Acumatica's context throw new PXSetPropertyException($"Failed to create file: {ex.Message}", PXErrorLevel.Error); } finally { // Always revert impersonation to avoid identity leaks impersonationContext.Undo(); } } } }
- Secure Credentials: Never hardcode usernames/passwords. Always use Acumatica's Secure Storage to protect sensitive information.
- Permissions: Ensure the Acumatica application pool identity has the right to call
LogonUser(adjust local security policy if needed). Also, assign a custom Acumatica permission to restrict who can run this action. - Cleanup: Always wrap impersonation in a
usingblock or ensureUndo()is called to revert the identity. - Network Access: Verify the Acumatica server can reach the network share (test the path from the server first).
- Error Handling: Use Acumatica's
PXSetPropertyExceptionto show user-friendly errors instead of raw exceptions.
内容的提问来源于stack exchange,提问作者Muralidharan Ramakrishnan

