http.Request에서 클라이언트의 IP 주소를 가져 오는 올바른 방법
모든 클라이언트의 IP 주소를 가져 오는 올바른 방법은 무엇입니까 http.Request
? 에서 PHP
의 많은있다 변수 내가 확인해야한다고는. Go에서도 동일합니까?
내가 찾은 것은 다음과 같습니다.
req.RemoteAddr
그리고 요청은 대소 문자를 구분합니까? 예를 들어 x-forwarded-for
는 X-Forwarded-For
및 X-FORWARDED-FOR
? (부터 req.Header.Get("X-FORWARDED-FOR")
)
http.Request 를 보면 다음과 같은 멤버 변수를 찾을 수 있습니다.
// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
//
// For client requests certain headers are automatically
// added and may override values in Header.
//
// See the documentation for the Request.Write method.
Header Header
// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string
를 사용 RemoteAddr
하여 원래 요청자 또는 마지막 프록시 (예 : 서버 앞에있는로드 밸런서 )의 주소 인 원격 클라이언트의 IP 주소 및 포트 (형식은 "IP : port")를 가져올 수 있습니다 .
이것이 당신이 가진 전부입니다.
그런 다음 대소 문자를 구분하지 않는 헤더를 조사 할 수 있습니다 (위의 문서에 따라). 즉, 모든 예제가 작동하고 동일한 결과를 생성합니다.
req.Header.Get("X-Forwarded-For") // capitalisation
req.Header.Get("x-forwarded-for") // doesn't
req.Header.Get("X-FORWARDED-FOR") // matter
내부적으로 http.Header.Get
키를 정규화 하기 때문 입니다. (를 통하지 않고 헤더 맵에 직접 액세스 Get
하려면 먼저 http.CanonicalHeaderKey 를 사용해야 합니다.)
마지막으로 "X-Forwarded-For"
클라이언트의 IP에 대한 더 많은 정보를 얻기 위해 살펴보고 싶은 필드 일 것입니다. 클라이언트가 원할 경우 거기에 무엇이든 넣을 수 있기 때문에 이것은 원격 측에서 사용되는 HTTP 소프트웨어에 크게 의존합니다. 또한 이 필드 의 예상 형식 은 쉼표 + 공백으로 구분 된 IP 주소 목록입니다. 선택한 단일 IP (아마도 목록의 첫 번째 IP)를 얻으려면 약간 구문 분석해야합니다. 예를 들면 다음과 같습니다.
// Assuming format is as expected
ips := strings.Split("10.0.0.1, 10.0.0.2, 10.0.0.3", ", ")
for _, ip := range ips {
fmt.Println(ip)
}
다음을 생성합니다.
10.0.0.1
10.0.0.2
10.0.0.3
여기 완전히 작동하는 예
package main
import (
// Standard library packages
"fmt"
"strconv"
"log"
"net"
"net/http"
// Third party packages
"github.com/julienschmidt/httprouter"
"github.com/skratchdot/open-golang/open"
)
// https://blog.golang.org/context/userip/userip.go
func getIP(w http.ResponseWriter, req *http.Request, _ httprouter.Params){
fmt.Fprintf(w, "<h1>static file server</h1><p><a href='./static'>folder</p></a>")
ip, port, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
//return nil, fmt.Errorf("userip: %q is not IP:port", req.RemoteAddr)
fmt.Fprintf(w, "userip: %q is not IP:port", req.RemoteAddr)
}
userIP := net.ParseIP(ip)
if userIP == nil {
//return nil, fmt.Errorf("userip: %q is not IP:port", req.RemoteAddr)
fmt.Fprintf(w, "userip: %q is not IP:port", req.RemoteAddr)
return
}
// This will only be defined when site is accessed via non-anonymous proxy
// and takes precedence over RemoteAddr
// Header.Get is case-insensitive
forward := req.Header.Get("X-Forwarded-For")
fmt.Fprintf(w, "<p>IP: %s</p>", ip)
fmt.Fprintf(w, "<p>Port: %s</p>", port)
fmt.Fprintf(w, "<p>Forwarded for: %s</p>", forward)
}
func main() {
myport := strconv.Itoa(10002);
// Instantiate a new router
r := httprouter.New()
r.GET("/ip", getIP)
// Add a handler on /test
r.GET("/test", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// Simply write some test data for now
fmt.Fprint(w, "Welcome!\n")
})
l, err := net.Listen("tcp", "localhost:" + myport)
if err != nil {
log.Fatal(err)
}
// The browser can connect now because the listening socket is open.
//err = open.Start("http://localhost:"+ myport + "/test")
err = open.Start("http://localhost:"+ myport + "/ip")
if err != nil {
log.Println(err)
}
// Start the blocking server loop.
log.Fatal(http.Serve(l, r))
}
이것이 내가 IP를 얻는 방법입니다.
func ReadUserIP(r *http.Request) string {
IPAddress := r.Header.Get("X-Real-Ip")
if IPAddress == "" {
IPAddress = r.Header.Get("X-Forwarded-For")
}
if IPAddress == "" {
IPAddress = r.RemoteAddr
}
return IPAddress
}
X-Real-Ip-첫 번째 실제 IP를 가져옵니다 (요청이 여러 NAT 소스 /로드 밸런서 뒤에있는 경우).
X-Forwarded-For-어떤 이유로 X-Real-Ip가 비어 있고 응답을 반환하지 않는 경우 X-Forwarded-For에서 가져옵니다.
- Remote Address - last resort (usually won't be reliable as this might be the last ip or if it is a naked http request to server ie no load balancer)
In PHP there are a lot of variables that I should check. Is it the same on Go?
This has nothing to do with Go (or PHP for that matter). It just depends on what the client, proxy, load-balancer, or server is sending. Get the one you need depending on your environment.
http.Request.RemoteAddr
contains the remote IP address. It may or may not be your actual client.
And is the request case sensitive? for example x-forwarded-for is the same as X-Forwarded-For and X-FORWARDED-FOR? (from req.Header.Get("X-FORWARDED-FOR"))
No, why not try it yourself? http://play.golang.org/p/YMf_UBvDsH
ReferenceURL : https://stackoverflow.com/questions/27234861/correct-way-of-getting-clients-ip-addresses-from-http-request
'developer tip' 카테고리의 다른 글
Django Rest Framework : 개체 생성 후 필드 업데이트 비활성화 (0) | 2020.12.25 |
---|---|
느린 요청이있을 때 Android Volley 이중 게시 (0) | 2020.12.25 |
특정 색상을 생성하기 위해 필요한 색상 회전을 계산하는 방법은 무엇입니까? (0) | 2020.12.25 |
브라우저 창 중앙에 요소를 배치하는 방법은 무엇입니까? (0) | 2020.12.24 |
두 파일이 동일한 지 확인하는 가장 빠른 해시 알고리즘은 무엇입니까? (0) | 2020.12.24 |