sql >> Databáze >  >> RDS >> Sqlserver

Go with SQL Server driver se nemůže úspěšně připojit, přihlášení se nezdařilo

Chci se podělit o své zkušenosti s vypracováním jednoduchého ukázkového jazykového databázového programu Go pomocí SQL Server Express 2008. Věřím, že následující poznatky budou platit pro jakoukoli verzi SQL Server od roku 2008 a novější.

Můj SQL Server Express byl dříve nainstalován s default instance spíše než named instance. Byl také nainstalován pro použití ověřování systému Windows. Obě tato nastavení si vyžádala další vývojová práce, kterou dělám. Další práce, kterou dělám, používá SQL Server Express na stejném počítači jako aplikace jako lokální databázový stroj. Očekával jsem, že budu moci používat ověřování Windows se serverem SQL v aplikaci Go.

Při hledání ovladače a malého ukázkového programu pro použití s ​​místním SQL Serverem a Go se objevila tato otázka. Napadlo mě přidat trochu dalších informací a vzorový program, abych pomohl ostatním začít a poučit se z mých chyb. Tento článek GoLang a MSSQL Databases:An Example mi také pomohl zvláště po tom, co jsem udělal dostatečné množství chyb, abych mu lépe rozuměl.

Finální verze mého testovacího programu je následující:

package main

import (
    "fmt"
    "log"
    "database/sql"
     _ "github.com/denisenkom/go-mssqldb"     // the underscore indicates the package is used
)    

func main() {
    fmt.Println("starting app")

    // the user needs to be setup in SQL Server as an SQL Server user.
    // see create login and the create user SQL commands as well as the
    // SQL Server Management Studio documentation to turn on Hybrid Authentication
    // which allows both Windows Authentication and SQL Server Authentication.
    // also need to grant to the user the proper access permissions.
    // also need to enable TCP protocol in SQL Server Configuration Manager.
    //
    // you could also use Windows Authentication if you specify the fully qualified
    // user id which would specify the domain as well as the user id.
    // for instance you could specify "user id=domain\\user;password=userpw;".

    condb, errdb := sql.Open("mssql", "server=localhost;user id=gouser;password=g0us3r;")
    if errdb  != nil {
        fmt.Println("  Error open db:", errdb.Error())
    }

    defer condb.Close()

    errdb = condb.Ping()
    if errdb != nil {
        log.Fatal(errdb)
    }

    // drop the database if it is there so we can recreate it
    // next we will recreate the database, put a table into it,
    // and add a few rows.
    _, errdb = condb.Exec("drop database mydbthing")
    if errdb != nil {
        fmt.Println("  Error Exec db: drop db - ", errdb.Error())
    }

    _, errdb = condb.Exec("create database mydbthing")
    if errdb  != nil {
        fmt.Println("  Error Exec db: create db - ", errdb.Error())
    }

    _, errdb = condb.Exec("use  mydbthing")
    if errdb  != nil {
        fmt.Println("  Error Exec db: using db - ", errdb.Error())
    }

    _, errdb = condb.Exec("create table junky (one int, two int)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: create table - ", errdb.Error())
    }

    _, errdb = condb.Exec("insert into junky (one, two) values (101, 201)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 1 - ", errdb.Error())
    }
    _, errdb = condb.Exec("insert into junky (one, two) values (102, 202)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 2 - ", errdb.Error())
    }
    _, errdb = condb.Exec("insert into junky (one, two) values (103, 203)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 3 - ", errdb.Error())
    }

    // Now that we have our database lets read some records and print them.
    var (
        one  int
        two  int
    )

    // documentation about a simple query and results loop is at URL
    // http://go-database-sql.org/retrieving.html
    // we use Query() and not Exec() as we expect zero or more rows to
    // be returned. only use Query() if rows may be returned.
    fmt.Println ("  Query our table for the three rows we inserted.")
    rows, errdb := condb.Query ("select one, two from junky")
    defer rows.Close()
    for rows.Next() {
        err:= rows.Scan (&one, &two)
        if err != nil {
            fmt.Println("  Error Query db: select - ", err.Error())
        } else {
            fmt.Printf("    - one %d and two %d\n", one, two)
        }
    }
    rows.Close()

    errdb = rows.Err()
    if errdb != nil {
        fmt.Println("  Error Query db: processing rows - ", errdb.Error())
    }

    fmt.Println("ending app")
}

Při prvním spuštění výše uvedené aplikace po provedení nezbytných změn nastavení serveru SQL Server vygeneruje následující výstup. Protože databáze při prvním spuštění programu neexistuje, zobrazí se vytištěné chybové hlášení. Nicméně při dalším spuštění databáze bude existovat a chybová zpráva při zrušení databáze exist nebude zobrazena.

starting app
  Error Exec db: drop db -  mssql: Cannot drop the database 'mydbthing', because it does not exist or you do not have permission.
  Query our table for the three rows we inserted.
    - one 101 and two 201
    - one 102 and two 202
    - one 103 and two 203
ending app

Instalace balíčku SQL Server Driver

První věc, kterou jsem musel udělat, bylo najít balíček ovladače databáze, který by fungoval s SQL Serverem. Doporučeno několik příspěvků stackoverflow github.com/denisenkom/go-mssqldb takže to je to, co se používá.

Chcete-li použít github.com/denisenkom/go-mssqldb balíček Nejprve jsem jej musel načíst z úložiště github pomocí go get github.com/denisenkom/go-mssqldb z okna příkazového prostředí vytvořeného spuštěním Git Shell .

Git Shell je shell github, který se instaluje jako součást instalace Git. Zjistil jsem, že musím spustit go get příkaz v Git Shell v pořadí go příkaz k nalezení git aplikaci a přístup k úložišti github. Když jsem se pokusil spustit go get příkaz z normálního příkazového shellu Viděl jsem chybovou zprávu označující, že git příkaz nebyl nalezen.

Po instalaci go-mssqldb balíček Podařilo se mi spustit ukázkovou aplikaci a stále se mi vyskytla chyba běhu z Open() . Výstup z mé aplikace byl následující:

starting app

Error Exec db: create db -  Unable to open tcp connection with host 'localhost:1433': dial tcp 127.0.0.1:1433: connectex: No connection could be made because the target machine actively refused it.

ending app

Povolení připojení TCP pro SQL Server

Po nějakém hledání jsem našel řadu různých stránek, které všechny naznačovaly, že chyba znamenala, že moje instance SQL Serveru nebyla nakonfigurována pro TCP/IP. Různé příspěvky naznačovaly, že potřebuji použít Sql Server Configuration Manager pro povolení TCP/IP.

Zjistil jsem, že ve skutečnosti existují dvě místa, kde je třeba povolit TCP/IP. Jedním z nich byly Client Protocols a to už bylo skutečně povoleno. Druhým však byly Protocols for MSSQLSERVER a v tom jeden TCP/IP byl zakázán. Povolil jsem tedy TCP/IP v Protocols for MSSQLSERVER poté restartujte službu SQL Server pomocí obslužného programu Service nástroje pro správu z ovládacího panelu.

Po použití sql.Open() jsem však měl stále problémy s jakýmkoli druhem dotazu . Viděl jsem výstup aplikace, který byl určitou variací následujícího. Chybová zpráva byla stejná, ale když volání funkcí měla chyby, mohla se změnit z jednoho běhu na druhý. Pokusil jsem se změnit připojovací řetězec uvedený v sql.Open() s žádnými jinými výsledky než různými chybovými zprávami.

starting app
  Error Exec db: create db -  driver: bad connection
  Error Exec db: create table -  driver: bad connection
ending app

Když jsem se dál probíral, našel jsem v úložišti github tuto poznámku:

Známé problémy

Modul SQL Server 2008 a 2008 R2 nemůže zpracovat přihlašovací záznamy, když není zakázáno šifrování SSL. Chcete-li vyřešit problém s SQL Server 2008 R2, nainstalujte SQL Server 2008 R2 Service Pack 2. Chcete-li vyřešit problém s SQL Server 2008, nainstalujte Microsoft SQL Server 2008 Service Pack 3 a balíček Cumulativeupdate 3 pro SQL Server 2008 SP3. Další informace:http://support.microsoft.com/kb/2653857

Stáhl jsem si tedy aktualizace, které jsem ve skutečnosti nikdy nenainstaloval. Během čekání na stahování jsem se více prohrabal a našel složku obsahující skutečný spustitelný soubor SQL Server spolu s Log složka obsahující řadu souborů ERRORLOG , ERRORLOG.1 , atd.

Protokoly serveru SQL Server uvádějí, že je vyžadován uživatel serveru SQL Server

Podívejte se do ERRORLOG soubor Nalezl jsem protokol chyb SQL Serveru s následujícími protokoly, které poskytly další díl skládačky:

2016-08-15 22:56:22.41 Server      SQL Server is now ready for client connections. This is an informational message; no user action is required.
2016-08-15 23:55:47.51 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.51 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]
2016-08-15 23:55:47.61 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.61 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: ::1]
2016-08-15 23:55:47.62 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.62 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]

Pak jsem si uvědomil, že ovladač Go SQL Server nepoužívá ověřování Windows, ale místo toho používá ověřování SQL Server. Pokusil jsem se použít ověřování systému Windows zadáním prázdného user id= zdálo se však, že to nefungovalo. Takže pomocí sqlcmd vytvořil jsem uživatele SQL Server.

1> create login gouser with password='g0us3r';
2> go
1> create user gouser for login gouser;
2> go

Dále jsem si stáhl a nainstaloval Microsoft SQL Server Management Studio. Toto je jiný nástroj než SQL Server Configuration Manager. Pomocí tohoto jsem provedl dvě věci:(1) zapnul ověřování SQL Server a ověřování systému Windows a (2) poskytl potřebná oprávnění pro mého nového uživatele serveru SQL Server gouser . Tento nástroj také poskytoval pěkné uživatelské rozhraní pro procházení SQL Serveru a jeho různých databází.

Ujistěte se, že vytvořený uživatel SQL má dostatečná oprávnění, aby jej bylo možné použít k připojení k serveru SQL a vytvoření databáze.

Některé úvahy o používání ověřování systému Windows

Po dalším výzkumu jsem zjistil, že mohu skutečně použít ověřování systému Windows, ale musí být poskytnuto zcela kvalifikované uživatelské jméno a jeho heslo. Pro prostředí používající Active Directory s názvem domény "AD" by plně kvalifikované ID uživatele bylo "AD\uživatelské jméno" a pro místního hostitele by bylo "\uživatelské jméno". Stále hledám možnost automatického použití přihlašovacích údajů aktuálně přihlášeného uživatele.

Po dalším průzkumu a nalezení pomoci od vývojářů ovladačů Go by mělo být ověření systému Windows s aktuální verzí možné, pokud sql.Open() nezahrnuje informace o uživateli ve smyslu "id uživatele=;heslo=;" by neměl být specifikován.

Tato forma automatického ověřování systému Windows vůči aktuálnímu uživateli je však povolena pouze v případě, že instance serveru SQL Server používá Kerberos s platným názvem Service Principal Name (SPN). Pokud provedete restart na své instanci SQL Server a v souboru ERRORLOG uvidíte následující protokol, SQL Server se nepodařilo inicializovat pomocí Kerberos.

2016-08-23 18:32:16.77 Server Knihovna SQL Server Network Interface nemohla zaregistrovat hlavní název služby (SPN) pro službu SQL Server. Chyba:0x54b, stav:3. Selhání registrace hlavního názvu služby může způsobit, že se integrované ověřování vrátí k NTLM namísto Kerberos. Toto je informativní zpráva. Další akce je vyžadována pouze v případě, že zásady autentizace vyžadují ověření Kerberos.

Viz také Jak se ujistit, že používáte ověřování Kerberos, když vytváříte vzdálené připojení k instanci SQL Server 2005, která také poskytuje některé další informace pomocí setspn příkaz k odstranění problému.

Viz také Knihovna síťového rozhraní SQL nemohla zaregistrovat SPN.

O důvěryhodném ověřování systému Windows (Aktualizováno na žádost @Richard od @xpt)

Windows Authentication je přihlašování k serveru SQL Server pomocí pověření Windows bez zadání uživatelského jména a hesla. Toto se nazývá důvěryhodné připojení pro sqlcmd nebo ODBC; nebo se nazývá Single-Sign-On pro go-mssqldb Balíček ovladače Go.

Z go-mssqldb 's readme v github,

"user id" - zadejte ID uživatele ověřování SQL Server nebo ID uživatele WindowsAuthentication ve formátu DOMAIN\User. Pokud je v systému Windows ID uživatele prázdné nebo chybí, použije se jednotné přihlášení.

Vyzkoušel jsem tedy se svým SQL Serverem 2008 R2 následující dva způsoby a oba fungují dobře:

condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=DONTCARE;")
condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=;")

Všimněte si, že použití server=localhost by selhalo, protože je důležité mít správný název hostitele, z tohoto názvu ovladač vytváří hlavní název služby SQL Server kerberos (SPN) a tento název se musí shodovat s názvem SQL Server. V testu jsem použil správný hlavní název služby (SPN), takže to funguje.




  1. Materializovaný pohled PostgreSQL

  2. Je možné vynutit kontrolu dat v MySQL pomocí regulárního výrazu

  3. Offline instalace MariaDB Cluster pro CentOS

  4. Obnovení hlavní databáze SQL Server