sql >> Database teknologi >  >> RDS >> Sqlserver

Gå med SQL Server-driveren kan ikke oprette forbindelse, login mislykkes

Jeg vil gerne dele min erfaring med at udarbejde et simpelt demo-Go sprogdatabaseprogram ved hjælp af SQL Server Express 2008. Jeg tror, ​​at følgende erfaringer vil gælde for enhver SQL Server-version fra 2008 og senere.

My SQL Server Express blev tidligere installeret med default instans i stedet for en named eksempel. Det blev også installeret til at bruge Windows-godkendelse. Begge disse indstillinger var påkrævet af andet udviklingsarbejde, som jeg laver. Det andet arbejde, jeg laver, bruger SQL Server Express på samme pc som applikationen som en lokal databasemotor. Jeg forventede at kunne bruge Windows-godkendelse med SQL Server i min Go-applikation.

På udkig efter en driver og et lille eksempelprogram til brug med en lokal SQL Server og Go, kom dette spørgsmål op i min søgning. Jeg tænkte at tilføje lidt yderligere information og et eksempelprogram for at hjælpe andre med at komme i gang og lære af mine fejl. Jeg fandt også denne artikel, GoLang og MSSQL-databaser:Et eksempel, som var nyttig, især efter at have lavet tilstrækkeligt mange fejl, så jeg forstod det bedre.

Den endelige version af mit testprogram er som følger:

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")
}

Første gang ovenstående applikation køres, når de nødvendige ændringer til SQL Server-indstillingerne er foretaget, vil den generere følgende output. Da databasen ikke eksisterer første gang programmet køres, vil du se fejlmeddelelsen udskrevet. Men efterfølgende gange den køres, vil databasen eksistere, og fejlmeddelelsen, når databasen slettes, vil ikke blive udlæst.

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

Installation af SQL Server Driver-pakken

Den første ting, jeg skulle gøre, var at finde en databasedriverpakke, der ville fungere med SQL Server. Adskillige stackoverflow-opslag anbefales github.com/denisenkom/go-mssqldb så det er det der bruges.

For at bruge github.com/denisenkom/go-mssqldb pakke, jeg skulle først hente den fra github-lageret ved hjælp af go get github.com/denisenkom/go-mssqldb fra kommandoskalvinduet oprettet ved at køre Git Shell .

Git Shell er github-skallen, der er installeret som en del af installationen af ​​Git. Jeg fandt ud af, at jeg var nødt til at køre go get kommandoen i Git Shell for at go kommandoen for at finde git applikation og få adgang til github-lageret. Da jeg prøvede at køre go get kommando fra en normal kommandoskal Jeg så en fejlmeddelelse, der indikerer, at git kommandoen kunne ikke findes.

Efter installation af go-mssqldb pakke Jeg var i stand til at køre mit eksempelprogram og blev ved med at løbe ind i en runtime-fejl fra Open() . Outputtet fra min applikation var følgende:

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

Aktivering af TCP-forbindelser til SQL Server

Efter lidt søgning fandt jeg en række forskellige sider, som alle indikerede, at fejlen betød, at min SQL Server-instans ikke var konfigureret til TCP/IP. De forskellige opslag viste, at jeg havde brug for at bruge Sql Server Configuration Manager for at aktivere TCP/IP.

Det, jeg opdagede, er, at der faktisk er to steder, hvor TCP/IP skal aktiveres. Den ene var Client Protocols og det var faktisk allerede aktiveret. Den anden var imidlertid Protocols for MSSQLSERVER og i den ene var TCP/IP deaktiveret. Så jeg aktiverede TCP/IP i Protocols for MSSQLSERVER sektionen, og genstartede derefter SQL Server-tjenesten ved hjælp af serviceværktøjet i Administrative værktøjer fra kontrolpanelet.

Jeg havde dog stadig problemer med enhver form for forespørgsel efter at have brugt sql.Open() . Jeg så applikationsoutput, der var en variation af følgende. Fejlmeddelelsen var den samme, men når funktionskald havde fejl kunne ændres fra en kørsel til den næste. Jeg prøvede at ændre forbindelsesstrengen angivet i sql.Open() uden andre resultater end forskellige fejlmeddelelser.

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

Jeg fandt denne note i github-lageret, mens jeg kiggede videre:

Kendte problemer

SQL Server 2008 og 2008 R2-motoren kan ikke håndtere login-poster, når SSL-kryptering ikke er deaktiveret. For at løse problemet med SQL Server 2008 R2 skal du installere SQL Server 2008 R2 Service Pack 2. For at løse problemet med SQL Server 2008 skal du installere Microsoft SQL Server 2008 Service Pack 3 og Cumulativeupdate-pakke 3 til SQL Server 2008 SP3. Flere oplysninger:http://support.microsoft.com/kb/2653857

Så jeg downloadede opdateringerne, som jeg faktisk aldrig installerede. Mens jeg ventede på download, søgte jeg mere og fandt mappen, der indeholdt den faktiske SQL Server eksekverbare sammen med Log mappe, der indeholder en række filer ERRORLOG , ERRORLOG.1 osv.

SQL Server-logfiler angiver, at SQL Server-bruger er påkrævet

Søger i ERRORLOG fil Jeg fandt en fejllog for SQL Server med følgende logfiler, som gav den næste brik i puslespillet:

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]

Jeg indså derefter, at Go SQL Server-driveren ikke brugte Windows-godkendelse, men i stedet brugte SQL Server-godkendelse. Jeg havde forsøgt at bruge Windows-godkendelse ved at angive et tomt user id= det så dog ikke ud til at virke. Så ved at bruge sqlcmd værktøj, oprettede jeg en SQL Server-bruger.

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

Dernæst downloadede og installerede jeg Microsoft SQL Server Management Studio. Dette er et andet værktøj end SQL Server Configuration Manager. Ved at bruge dette gjorde jeg to ting:(1) aktiverede SQL Server Authentication samt Windows Authentication og (2) gav de nødvendige tilladelser til min nye SQL Server-bruger gouser . Dette værktøj gav også en god brugergrænseflade til at gennemse SQL Server og dens forskellige databaser.

Sørg for, at den SQL-bruger, du opretter, har tilstrækkelige tilladelser, så den kan bruges til at oprette forbindelse til SQL Server og oprette en database.

Nogle overvejelser ved brug af Windows-godkendelse

Efter yderligere forskning fandt jeg ud af, at jeg faktisk kunne bruge Windows-godkendelse, men det fuldstændigt kvalificerede bruger-id og dets adgangskode skal angives. For et miljø, der bruger Active Directory med domænenavnet "AD" vil det fuldt kvalificerede bruger-id være "AD\brugerid" og for den lokale vært "\brugerid". Jeg undersøger stadig, hvordan jeg automatisk kan bruge legitimationsoplysningerne for den aktuelt loggede bruger.

Efter yderligere forskning og hjælp fra Go-driverudviklerne, burde Windows-godkendelse med den nuværende være mulig, hvis sql.Open() inkluderer ikke brugeroplysningerne, der betyder "bruger-id=;adgangskode=;" skal ikke angives.

Denne form for automatisk Windows-godkendelse mod den aktuelle bruger er dog kun tilladt, hvis SQL Server-instansen bruger Kerberos med et gyldigt Service Principal Name (SPN). Hvis du genstarter din forekomst af SQL Server, og du ser følgende log i din ERRORLOG-fil, var SQL Server ikke i stand til at initialisere med Kerberos.

2016-08-23 18:32:16.77 Server SQL Server Network Interface-biblioteket kunne ikke registrere Service Principal Name (SPN) for SQL Server-tjenesten. Fejl:0x54b, tilstand:3. Manglende registrering af et SPN kan medføre, at integreret godkendelse falder tilbage til NTLM i stedet for Kerberos. Dette er en informationsmeddelelse. Yderligere handling er kun påkrævet, hvis Kerberos-godkendelse er påkrævet af godkendelsespolitikker.

Se også Sådan sikrer du dig, at du bruger Kerberos-godkendelse, når du opretter en fjernforbindelse til en forekomst af SQL Server 2005, som også giver nogle yderligere oplysninger ved hjælp af setspn kommando for at rette problemet.

Se også SQL Network Interface-biblioteket kunne ikke registrere SPN.

Om betroet Windows-godkendelse (Opdateret efter anmodning fra @Richard af @xpt)

Windows-godkendelse er at logge på SQL Server med Windows-legitimationsoplysninger uden at angive et bruger-id og en adgangskode. Dette kaldes betroet forbindelse for sqlcmd eller ODBC; eller kaldet Single-Sign-On for go-mssqldb Go driverpakke.

Fra go-mssqldb 's readme i github,

"bruger-id" - indtast bruger-id'et til SQL Server Authentication eller Windows Authentication-bruger-id'et i formatet DOMAIN\User. På Windows, hvis bruger-id er tomt eller mangler, bruges Single-Sign-On.

Så jeg prøvede følgende to måder med min SQL Server 2008 R2, og begge fungerer fint:

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

Bemærk, at brugen af ​​server=localhost ville mislykkes, da det er vigtigt at have det korrekte værtsnavn, fra det navn bygger driveren SQL Server kerberos Service Principal Name (SPN), og det navn skal matche SQL Servers. Jeg brugte et korrekt Service Principal Name (SPN) med min test, så det virker.




  1. Beskytter mysql_real_escape_string() FULDSTÆNDIG mod SQL-injektion?

  2. Sådan opretter du en ikke-nul kolonne i en visning

  3. PL/SQL:hvordan beder jeg brugerinput i en procedure?

  4. Guide til design af database til restaurantordresystem i MySQL