首页 > 解决方案 > MySQL + ODBC 为什么我可以在没有任何凭据的情况下连接 SQLConnect

问题描述

我正在尝试从带有 C 程序的 Windows 客户端连接到在 Ubuntu 18.04 上运行的 MySQL 数据库。

使用 SQLConnect ODBC API 连接时,即使我没有提供用户密码,连接也会成功。

如果我尝试使用错误的密码连接,我无法连接,如果我尝试使用正确的密码,我可以连接(这显然是预期的行为)

如何在不提供密码的情况下连接到 MySQL 数据库?

我错过了与 MySQL 配置相关的内容吗?

这是我的环境:

MySQL 版本:服务器版本:5.7.29-0ubuntu0.18.04.1 (Ubuntu)
ODBC 驱动程序版本:MySQL ODBC 8.0 Unicode 驱动程序 8.00.15.00
客户端:Win8.1 x64 pro

和代码:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#include <sql.h>
#include <sqlext.h>

#define SUCCEEDED(x) (SQL_SUCCESS == x || SQL_SUCCESS_WITH_INFO == x)

void ShowError(SQLHANDLE env, SQLHANDLE dbc, SQLHANDLE stmt);

int _tmain(int argc, TCHAR* argv[])
{
    SQLHANDLE env = NULL;
    SQLHANDLE dbc = NULL;
    SQLHANDLE stmt = NULL;
    SQLSMALLINT fieldCount = 0;
    SQLRETURN ret;
    TCHAR bufWhereWeAre[1000];
    LPCTSTR whereWeAre = _T("starting");
    int currentLine = 0;
    do
    {
        whereWeAre = _T("alloc env");
        ret = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &env);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("set env attr");
        ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, SQL_NTS);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("alloc dbc");
        ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("connect");
        // connection succeeds using the right credential
        //ret = SQLConnect(dbc, _T("UBUNTU18"), SQL_NTS, _T("admin"), SQL_NTS, _T("The actual password for admin"), 0);
        // connection succeeds if password is not provided (EXPECTING credential error)
        //ret = SQLConnect(dbc, _T("UBUNTU18"), SQL_NTS, _T("admin"), SQL_NTS, NULL, 0);
        // connection succeeds if no credential is provided (EXPECTING credential error)
        //ret = SQLConnect(dbc, _T("UBUNTU18"), SQL_NTS, NULL, 0, NULL, 0);
        // connection fails with wrong credential (expected behavior)
        ret = SQLConnect(dbc, _T("UBUNTU18"), SQL_NTS, _T("admin"), SQL_NTS, _T("wrong password for admin"), 0);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("alloc stmt");
        ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("execdirect");
        ret = SQLExecDirect(stmt, _T("select current_user();"), SQL_NTS);
        //ret = SQLExecDirect(stmt, _T("SELECT T.`term_id` AS term_id,T.`name` AS name,T.`slug` AS slug,T.`term_group` AS term_group FROM `wp_terms` T"), SQL_NTS);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("num result cols");
        ret = SQLNumResultCols(stmt, &fieldCount);
        if (!SUCCEEDED(ret))
            break;

        whereWeAre = _T("fetch data");
        ret = SQLFetch(stmt);
        currentLine = 0;
        while (SUCCEEDED(ret))
        {
            TCHAR buf[1000];
            int bufSize = sizeof(buf) / sizeof(TCHAR);
            int i;

            ++currentLine;
            for (i=1; i<=fieldCount; i++)
            {
                SQLLEN len = 0;
                _stprintf_s(bufWhereWeAre, bufSize, _T("line %d, field %d"), currentLine, i);
                whereWeAre = bufWhereWeAre;
                ret = SQLGetData(stmt, i, SQL_C_TCHAR, buf, sizeof(buf)/sizeof(TCHAR)-1, &len);
                if (!SUCCEEDED(ret))
                    break;
                _tprintf(buf);
                if (i == fieldCount)
                    _tprintf("\n");
                else
                    _tprintf("\t");
            }
            ret = SQLFetch(stmt);
        }
        if (SQL_NO_DATA_FOUND != ret
            && !SUCCEEDED(ret))
            break;

        ret = SQLFreeStmt(stmt, SQL_DROP);
        if (!SUCCEEDED(ret))
            break;
        stmt = NULL;
    }
    while (FALSE);

    if (!SUCCEEDED(ret))
    {
        _tprintf(_T("%s\n"), whereWeAre);
        ShowError(env, dbc, stmt);
    }
    if (NULL != stmt)
        SQLFreeStmt(stmt, SQL_DROP);
    if (NULL != dbc)
        SQLFreeConnect(dbc);
    if (NULL != env)
        SQLFreeEnv(env);
    return 0;
}

void ShowError(SQLHANDLE env, SQLHANDLE dbc, SQLHANDLE stmt)
{
    SQLTCHAR state[100];
    SQLINTEGER nativeError = 0;
    SQLTCHAR errorMsg[1000];
    int sizeErrorMsgInTCHAR = sizeof(errorMsg)/sizeof(TCHAR) - 1; // -1: for possibly buggy drivers...
    SQLSMALLINT returnedErrorMsgSize = 0;

    SQLRETURN ret = SQLError(env, dbc, stmt, state, &nativeError, errorMsg, sizeErrorMsgInTCHAR, &returnedErrorMsgSize);
    if (!SUCCEEDED(ret))
        _tprintf(_T("SQLError returned an error...: %d"), (int) ret);
    else
    {
        returnedErrorMsgSize = min(max(0, returnedErrorMsgSize), sizeErrorMsgInTCHAR);
        errorMsg[returnedErrorMsgSize] = 0;
        _tprintf(_T("%s\n"), errorMsg);
    }
}

标签: mysqlconnectionodbc

解决方案


推荐阅读