簡體   English   中英

使用Dynamics GP用戶名和密碼的SqlConnection-用戶登錄失敗

[英]SqlConnection using Dynamics GP username and password — Login failed for user

我在為Dynamics GP編寫加載項,並嘗試運行自定義存儲過程,但是當我嘗試打開連接時,出現一條錯誤消息,提示“用戶登錄失敗:”。

如果我手動使用系統管理員的用戶名和密碼,那么一切都會正常執行。 但是,我想使用登錄Dynamics GP的用戶名和密碼。

string gpUsername = Dynamics.Globals.UserId.Value;
string gpPassword = Dynamics.Globals.SqlPassword.Value;
string companyDb = Dynamics.Globals.IntercompanyId.Value;
string dataSource = "sql-server-name";

SqlConnectionStringBuilder constringBuilder = new SqlConnectionStringBuilder();
constringBuilder.UserID = gpUsername;
constringBuilder.Password = gpPassword;
constringBuilder.InitialCatalog = companyDb;
constringBuilder.DataSource = dataSource;
constringBuilder.WorkstationID = Environment.MachineName;
constringBuilder.MultipleActiveResultSets = true;
constringBuilder.ApplicationName = $"{FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductName} (GP)";
constringBuilder.IntegratedSecurity = false;
string constring = constringBuilder.ConnectionString;
SqlConnection con = new SqlConnection(constring);
con.Open();

這是完整的堆棧跟蹤:

Dynamics.exe Warning: 0 : Exception occurred while updating Item class 1255. Review the error message below.
    System.Data.SqlClient.SqlException (0x80131904): Login failed for user '<username>'.
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at Dyn2Bib.GPAddIn.ProcessTransaction(String srs, String srsName, String changeType)
ClientConnectionId:1a4c93c1-0efd-4590-8c9f-98265eaafaa2
Error Number:18456,State:1,Class:14

如果我改變了DataSourceconstringBuilder使用Dynamics.Globals.SqlDataSourceName.Value ,它看起來像它無法找到網絡中的所有的數據源,並給出了錯誤:

Dynamics.exe Warning: 0 : Exception occurred while updating Item class 1255. Review the error message below.
    System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception (0x80004005): The network path was not found
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at Dyn2Bib.GPAddIn.ProcessTransaction(String srs, String srsName, String changeType)
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:53,State:0,Class:20

如果我將連接字符串打印到屏幕上,它看起來是正確的,並且正如我所提到的,如果我手動使用系統管理員帳戶,它將起作用。

我可以使用Dynamics GP帳戶直接連接到SQL Server嗎? 服務器上有一個相應的登錄名,因此似乎應該已經正確配置了它。 有人知道我在做什么錯嗎? 我是否需要對Dynamics GP帳戶進行任何更改以允許其使用SQL身份驗證進行連接?

我假設登錄Dynamics GP的人的用戶名和密碼僅是Dynamics GP應用程序用戶,而不是實際的數據庫用戶。

您可以通過將身份驗證更改為Windows身份驗證來解決此問題

這可以通過以下方式實現:

  1. 創建一個Windows組
  2. 使用應該能夠運行自定義SP的每個Windows用戶填充該Windows組
  3. 使用SQL Server Management Studio,將此窗口組添加為SQL Server登錄名
  4. 在您的代碼中

刪除這些行:

constringBuilder.UserID = gpUsername;
constringBuilder.Password = gpPassword;

並像這樣更改此行:

 constringBuilder.IntegratedSecurity = true;

這意味着將使用其Windows憑據而不是(無效)SQL憑據建立連接

通過完成步驟1-3,這些Windows憑據先前已被授予服務器登錄訪問權限

這還不是故事的結局。 現在,您需要啟用組剛剛訪問您的SP

  1. 使用存儲過程在數據庫中創建數據庫角色
  2. 授予該角色執行對自定義SP的訪問權限
  3. 最后,要將其鏈接起來,請編輯您在步驟3中創建的登錄名,授予它對數據庫的訪問權限,並將其添加到在步驟5中創建的角色中

復雜? 是。 但是,授予用戶訪問數據庫的權限非常重要。 這條路

  • 用戶可以登錄並運行SP,而無其他操作。
  • 要授予和刪除用戶,可以在windows組中添加或刪除用戶(如果需要,可以重復使用現有的GP windows組)
  • 如果創建需要訪問的其他數據庫對象,則授予數據庫角色訪問權限

如果您希望使用此解決方案,我可以在其上進行擴展。

做到這一點的方法是使用GP中的連接對象

 using Dex = Microsoft.Dexterity.Applications; internal static SqlConnection conn = new SqlConnection(); internal static SqlConnection GetOpenGPConnection() { try { //Call Startup int resp = GPConnection.Startup(); // Create the connection object Microsoft.Dexterity.GPConnection GPConn = new GPConnection(); // Initialize GPConn.Init("MyVSTDCompanyid", "myVSTDGPAuthCode"); // get this from Microsoft GP Dev Tools Support conn.ConnectionString = String.Format("Database = {0}", Dex.Dynamics.Globals.IntercompanyId.Value); GPConn.Connect(conn, Dex.Dynamics.Globals.SqlDataSourceName, Dex.Dynamics.Globals.UserId, Dex.Dynamics.Globals.SqlPassword); if ((GPConn.ReturnCode & (int)GPConnection.ReturnCodeFlags.SuccessfulLogin) == (int)GPConnection.ReturnCodeFlags.SuccessfulLogin) { return conn; } else {//... user authenticaltion failed - backup plan? fallback to windows auth? return null } } catch (Exception ex) { // your catch handling mechanism } } 

GP使用SQL身份驗證。 GP用戶是SQL登錄名。 (您可以將Windows Auth與使用FastPath的GP一起使用。越來越流行,MS也一直在談論其對本機的支持)

盡管用戶具有SQL登錄名,但是應用程序在SQL上創建帳戶並哈希密碼。 這是為了防止用戶使用諸​​如Crystal之類的工具來查詢他們無權訪問的數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM