如何在没有登录凭据的情况下编写连接字符串.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...
我可以看到一些信息:
- 由于缺少用户名,访问被拒绝。
MySqlConnector
. 抛出异常
问题:
- 我可以在没有登录凭据的情况下编写连接字符串吗?
- 如果有人能向我解释在作为参数传递给
.UseMySql(cnn_str vs. MySqlConnection)
. 时,MySqlConnection
实例在连接字符串上有哪些优点和潜在缺点,我会很高兴
感谢任何帮助或解释,在此先感谢。
更多技术细节
硬件:RaspberryPi 4 B 型
SW:
- OS:Debian GNU/Linux 11(靶心)。
- 本地OS账户:pi
- SQL:Mariadb 10.5.12 启用了插件 unix_socket 身份验证。
- 应用服务器:nginx/1.18.0
应用程序:.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
对象来传递连接字符串;这在实践中可能可以忽略不计。
我正在寻找使用连接字符串的解决方案,而无需为 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...
我可以看到一些信息:
- 由于缺少用户名,访问被拒绝。
MySqlConnector
. 抛出异常
问题:
- 我可以在没有登录凭据的情况下编写连接字符串吗?
- 如果有人能向我解释在作为参数传递给
.UseMySql(cnn_str vs. MySqlConnection)
. 时,
MySqlConnection
实例在连接字符串上有哪些优点和潜在缺点,我会很高兴
感谢任何帮助或解释,在此先感谢。
更多技术细节
硬件:RaspberryPi 4 B 型
SW:
- OS:Debian GNU/Linux 11(靶心)。
- 本地OS账户:pi
- SQL:Mariadb 10.5.12 启用了插件 unix_socket 身份验证。
- 应用服务器:nginx/1.18.0
应用程序:.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
对象来传递连接字符串;这在实践中可能可以忽略不计。