如何在没有登录凭据的情况下编写连接字符串.net MySqlConnector/Pomelo.EntityFrameworkCore.MySql?

How to compose a connection string without login credentials .net MySqlConnector/Pomelo.EntityFrameworkCore.MySql?

我正在寻找使用连接字符串的解决方案,而无需为 MariaDB 服务器指定用户名和密码。我在同一台机器上 运行 应用程序和数据库服务器,所以我决定使用 unix_socket 身份验证。

重现步骤

我有两个连接字符串,其中两个变体都没有指定密码 属性:

a)

string cnn_str = @" 
Server=/run/mysqld/mysqld.sock;
Port=3306;
Database=mwsdb;
Protocol=unix;
AllowUserVariables=true;
UseAffectedRows=false;";

b) 变体与第一个变体相同,仅扩展了 uid 属性(受异常启发)

// appends user name - user that runs the application
// in my case the user name is 'pi'
cnn_str += $"Uid={Environment.UserName};";

连接数据库的代码:

1)MySqlConnector

var connection = new MySqlConnection(cnn_str);
using (connection)
{
    connection.Open();
}

2) 我在 Program.cs 中使用 Pomelo.EF.UseMySql()

配置数据库上下文服务的方式
builder.Services.AddDbContext<MwsDbContext>(dbContextOptions => dbContextOptions
/* either 2.1) */     .UseMySql(cnn_str, ServerVersion.AutoDetect(cnn_str))
/* or 2.2) */       // .UseMySql(new MySqlConnection(cnn_str), ServerVersion.AutoDetect(cnn_str))
);

问题

我使用简单的代码(控制台应用程序)来测试与 MariaDB 的连接并将结果放入 table。

Code Connection string Result
1 a) exception
1 b) works
2.1 a) exception
2.1 b) works
2.2 a) exception
2.2 b) works

抛出的异常总是相同的,并表示:

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      MySqlConnector.MySqlException (0x80004005): Access denied for user ''@'localhost'
 ...full exception output below...

我可以看到一些信息:

问题:

  1. 我可以在没有登录凭据的情况下编写连接字符串吗?
  2. 如果有人能向我解释在作为参数传递给 .UseMySql(cnn_str vs. MySqlConnection).
  3. 时,MySqlConnection 实例在连接字符串上有哪些优点和潜在缺点,我会很高兴

感谢任何帮助或解释,在此先感谢。

更多技术细节

硬件:RaspberryPi 4 B 型

SW:

应用程序:.NET 6 WEB API 和 ConsoleApp(均经过测试),包:

<PackageReference Include="MySqlConnector" Version="2.1.8" /> 
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />

关于我的项目设置的其他细节:

创建系统本地用户帐户

sudo useradd -r pi

MariaDB

套接字文件路径:

root@rpi:~# ls /run/mysqld
mysqld.pid  mysqld.sock

Mariadb 配置文件 /etc/mysql/my.cnf 包含:

[client-server]
socket = /run/mysqld/mysqld.sock

SQL select 定位文件路径:

MariaDB [(none)]> show variables like 'socket';
+---------------+-------------------------+
| Variable_name | Value                   |
+---------------+-------------------------+
| socket        | /run/mysqld/mysqld.sock |
+---------------+-------------------------+
1 row in set (0.002 sec)

SQL 命令在 MariaDB 服务器数据库中创建用户并授予系统用户权限:

CREATE USER 'pi'@localhost IDENTIFIED VIA unix_socket;
GRANT ALL PRIVILEGES ON mwsdb.* TO 'pi'@localhost IDENTIFIED VIA unix_socket;

异常

MySqlConnector.MySqlException (0x80004005): Access denied for user ''@'localhost'
at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int32 startTickCount, ILoadBalancer loadBalancer, IOBehavior ioBehavior, CancellationToken canc>
at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, String logMessage, Int32 startTickCount, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src>
at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/Co>
at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/Co>
at MySqlConnector.MySqlConnection.CreateSessionAsync(ConnectionPool pool, Int32 startTickCount, Nullable`1 ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlConnection>
at MySqlConnector.MySqlConnection.OpenAsync(Nullable`1 ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlConnection.cs:line 406
at MySqlConnector.MySqlConnection.Open() in /_/src/MySqlConnector/MySqlConnection.cs:line 369
at Microsoft.EntityFrameworkCore.ServerVersion.AutoDetect(String connectionString)
at Program.<>c__DisplayClass0_0.<<Main>$>b__3(DbContextOptionsBuilder dbContextOptions) in /home/Prog>
at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_0`2.<AddDbContext>b__0(IServiceProvider p, DbContextOptionsBuilder b)
at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action`2 optionsAction)
at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass17_0`1.<AddCoreServices>b__0(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEng>
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEng>
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Program.<Main>$(String[] args) in /home/Program.cs:line 72

Program.cs:第 72 行

应用迁移。

l. 72:    using MwsDbContext? context = app.Services.CreateScope().ServiceProvider.GetService<MwsDbContext>();
l. 73:    context?.Database.Migrate();

Am I able to compose a connection string without login credentials?

没有。 MySqlConnector 需要指定 UserID,即使使用 Unix 套接字也是如此。 this issue.

中对此进行了介绍

解决方法是明确设置用户名:

var builder = new MySqlConnectionStringBuilder("...connection string...");
builder.UserID = Environment.UserName;
using var connection = new MySqlConnection(builder.ConnectionString);

(或者只是 hard-code ;Username = pi 在你的连接字符串中。)

explain to me what pros and potential cons has MySqlConnection instance over connection string when passing as argument to .UseMySql(cnn_str vs. MySqlConnection).

这两种方法看起来相当等价:connection string vs connection

一个使用提供的连接字符串;另一个读取 DbConnection.ConnectionString 属性 并使用该连接字符串。前者的效率会稍微高一些,因为它不会创建一个额外的 MySqlConnection 对象来传递连接字符串;这在实践中可能可以忽略不计。