2017-02-08 11 views
0

Я пытаюсь понять, как получить клиентские сертификаты на веб-сервере Go. Вот код сервера:Как получить клиентские сертификаты на сервере Go HTTPS

package main 

import (
    "log" 
    "net/http" 
    "net/http/httputil" 
) 

func defaultHandler(w http.ResponseWriter, r *http.Request) { 
    dump, err := httputil.DumpRequest(r, true) 
    log.Println("HTTP request", r, string(dump), err) 
    log.Println("HTTP TLS", r.TLS, string(r.TLS.TLSUnique)) 
    certs := r.TLS.PeerCertificates 
    log.Println("HTTP CERTS", certs) 
    w.WriteHeader(http.StatusMethodNotAllowed) 
    w.Write([]byte("Hello")) 
} 

func main() { 
    http.HandleFunc("/", defaultHandler) 
    http.ListenAndServeTLS(":8080", "server.crt", "server.key", nil) 
} 

и здесь код клиента

package main 

import (
    "crypto/tls" 
    "io/ioutil" 
    "log" 
    "net/http" 
    "os" 
) 

func HttpClient() (client *http.Client) { 
    uckey := os.Getenv("X509_USER_KEY") 
    ucert := os.Getenv("X509_USER_CERT") 
    x509cert, err := tls.LoadX509KeyPair(ucert, uckey) 
    if err != nil { 
     panic(err.Error()) 
    } 
    certs := []tls.Certificate{x509cert} 
    if len(certs) == 0 { 
     client = &http.Client{} 
     return 
    } 
    tr := &http.Transport{ 
     TLSClientConfig: &tls.Config{Certificates: certs, 
     InsecureSkipVerify: true}, 
    } 
    client = &http.Client{Transport: tr} 
    return 
} 

func main() { 
    rurl := "https://localhost:8080" 
    client := HttpClient() 
    req, err := http.NewRequest("GET", rurl, nil) 
    if err != nil { 
     log.Println("Unable to make GET request", err) 
     os.Exit(1) 
    } 
    req.Header.Add("Accept", "*/*") 
    resp, err := client.Do(req) 
    if err != nil { 
     log.Println(err) 
     os.Exit(1) 
    } 
    defer resp.Body.Close() 
    data, err := ioutil.ReadAll(resp.Body) 
    log.Println(string(data)) 
} 

Если я бегу как сервер и клиент, я вижу следующие на стороне сервера:

2017/02/08 15:46:49 HTTP request &{GET/HTTP/1.1 1 1 map[User-Agent:[Go-http-client/1.1] Accept:[*/*] Accept-Encoding:[gzip]] {} 0 [] false localhost:8080 map[] map[] <nil> map[] 127.0.0.1:58941/0xc4204ef080 <nil> <nil> 0xc420014d40} GET/HTTP/1.1 
Host: localhost:8080 
Accept: */* 
Accept-Encoding: gzip 
User-Agent: Go-http-client/1.1 

<nil> 
2017/02/08 15:46:49 HTTP TLS &{771 true false 49195 true localhost [] [] [] [] [203 144 196 105 155 216 89 105 83 90 93 4]} ːiSZ] 
2017/02/08 15:46:49 HTTP CERTS [] 

As вы можете видеть, что сертификаты клиента пусты.

Хотя если я вызываю локон вызов на сервер предоставления своих сертификатов, то я могу увидеть сертификаты сервера:

curl -L -k --key mykey.key --cert mycert.pem -vvv https://localhost:8080 
* Trying 127.0.0.1... 
* TCP_NODELAY set 
* Connected to localhost (127.0.0.1) port 8080 (#0) 
* ALPN, offering http/1.1 
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH 
* successfully set certificate verify locations: 
* CAfile: /opt/local/share/curl/curl-ca-bundle.crt 
    CApath: none 
* TLSv1.2 (OUT), TLS header, Certificate Status (22): 
* TLSv1.2 (OUT), TLS handshake, Client hello (1): 
* TLSv1.2 (IN), TLS handshake, Server hello (2): 
* TLSv1.2 (IN), TLS handshake, Certificate (11): 
* TLSv1.2 (IN), TLS handshake, Server key exchange (12): 
* TLSv1.2 (IN), TLS handshake, Server finished (14): 
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16): 
* TLSv1.2 (OUT), TLS change cipher, Client hello (1): 
* TLSv1.2 (OUT), TLS handshake, Finished (20): 
* TLSv1.2 (IN), TLS change cipher, Client hello (1): 
* TLSv1.2 (IN), TLS handshake, Finished (20): 
* SSL connection using TLSv1.2/ECDHE-ECDSA-AES128-GCM-SHA256 
* ALPN, server accepted to use http/1.1 
* Server certificate: 
* subject: C=US; ST=NY; L=Town; O=Bla-Bla 
* start date: Feb 8 14:12:06 2017 GMT 
* expire date: Feb 6 14:12:06 2027 GMT 
* issuer: C=US; ST=NY; L=Ithaca; O=Cornell 
* SSL certificate verify result: self signed certificate (18), continuing anyway. 
> GET/HTTP/1.1 
> Host: localhost:8080 
> User-Agent: curl/7.52.1 
> Accept: */* 

Как вы можете видеть SSL переговоры на месте и скручивание клиент успешно передает сертификат сервера. Мне нужно получить доступ к сертификату клиента на стороне сервера для обеспечения правильной аутентификации. Но пока я не вижу никакого сертификата клиента.

Любая помощь действительно приветствуется. Thanks, Valentin.

ответ

3

Клиент не должен отправлять сертификат, если не запрошено. Установите ClientAuth в tls.Config на соответствующий tls.ClientAuthType.

Например, только просьбу о том, что клиент посылает сертификат, вы можете использовать:

server := &http.Server{ 
    Addr: ":8080", 
    TLSConfig: &tls.Config{ 
     ClientAuth: tls.RequestClientCert, 
    }, 
} 

server.ListenAndServeTLS("server.crt", "server.key") 
+0

Вот так, спасибо. – Valentin

 Смежные вопросы

  • Нет связанных вопросов^_^