Pārlūkot izejas kodu

tracking picture worked with correct cookie settings.

master
Patrick Peng Sun pirms 8 gadiem
vecāks
revīzija
29c9156975
4 mainītis faili ar 195 papildinājumiem un 6 dzēšanām
  1. +117
    -2
      crmpixel.go
  2. +71
    -0
      crmpixel_test.go
  3. +1
    -1
      main.go
  4. +6
    -3
      server.go

+ 117
- 2
crmpixel.go Parādīt failu

@@ -2,16 +2,131 @@ package main

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log"
"math/rand"
"net/http"
"strings"
"time"
)

func crmpixel(w http.ResponseWriter, r *http.Request) {
func crmpixelImage() (pixel []byte, err error) {
b64pixel := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QcIBzEJ3JY/6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAADUlEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg=="
pixel, err := base64.StdEncoding.DecodeString(b64pixel)
pixel, err = base64.StdEncoding.DecodeString(b64pixel)
return
}

func crmpixel(w http.ResponseWriter, r *http.Request) {

cookie, lead := crmpixelCookie(r)
log.Println(lead)
http.SetCookie(w, &cookie)

//send out pixel 1x1 transparent png file
pixel, err := crmpixelImage()
if err == nil {
w.Write(pixel)
} else {
fmt.Fprint(w, "decodig wrong")
}
}

func crmpixelCookie(r *http.Request) (ret http.Cookie, info crmdLead) {
cookie, leadok := r.Cookie("biukop_cl") //crm lead

if leadok != nil {
ret, info = createNewCookie(r)
return
}

valid, info := isValidCookieBiukopCL(cookie.Value)
if !valid {
ret, info = createNewCookie(r)
return
}

//refresh expiration
ret = *cookie
ret.Expires = time.Now().Add(10 * 365 * 24 * time.Hour)

return
}

func createNewCookie(r *http.Request) (ret http.Cookie, info crmdLead) {
expiration := time.Now().Add(10 * 365 * 24 * time.Hour)
info = crmCreateNewAnonymousLeadByHTTPRequest(r)
cookieValue := buildBiukopCLValue(info.ID)
ret = http.Cookie{Name: "biukop_cl", Value: cookieValue, Expires: expiration}
return
}

func crmCreateNewAnonymousLeadByHTTPRequest(r *http.Request) (info crmdLead) {
info.FirstName = "Anonymous"
info.LastName = "User"
info.Password = "Password"
info.Status = "Anonymous"
info.Description = "Anonymous from " + r.RemoteAddr
info.ForceDuplicate = true
b, err := json.Marshal(info)
if err != nil {
return
}
entity, err := crmCreateEntity("Lead", b)
if err == nil || isErrIndicateDuplicate(err) {
info, _ = entity.(crmdLead)
}
return
}

func isValidCookieBiukopCL(cookieValue string) (valid bool, info crmdLead) {
valid = false

//correctly split string
s := strings.Split(cookieValue, "|")
if len(s) != 4 || s[0] == "" {
return
}
id, nonce, timestamp, signature := s[0], s[1], s[2], s[3]

//check signature
combined := id + nonce
expected := calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete)
if expected != signature {
return
}

//find lead data
info, err := crmpixelLead(id)
if err != nil {
return
}
valid = true
return
}

func buildBiukopCLsignature(id, nonce string) (timestamp, signature string) {
combined := id + nonce
timestamp = fmt.Sprintf("%d", time.Now().Unix())
signature = calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete)
return
}

func buildBiukopCLValue(id string) (ret string) {
rand.Seed(time.Now().Unix())
nonce := fmt.Sprintf("%d", rand.Intn(655352017))
timestamp, signature := buildBiukopCLsignature(id, nonce)
strs := []string{id, nonce, timestamp, signature} //order is very important
ret = strings.Join(strs, "|")
return
}

func crmpixelLead(id string) (info crmdLead, err error) {
entity, err := crmGetEntity("Lead", id)
info, ok := entity.(crmdLead)
if !ok {
err = errors.New("search lead, return a bad entity type")
}
return
}

+ 71
- 0
crmpixel_test.go Parādīt failu

@@ -0,0 +1,71 @@
package main

import (
"io/ioutil"
"log"
"net/http"
"testing"
)

func TestCrmPixelCookie(t *testing.T) {
req := buildReqCrmPixel()
rr, _ := getHTTPResponse(req, crmpixel)

//check Set-Cookie
v, ok := rr.HeaderMap["Set-Cookie"] //biukop_cl=59610affc2ccce92d|323295325|1499532031|e0010c3e24a201665b783e2c48ab323b87ef52b7; Expires=Tue, 06 Jul 2027 16:40:31 GMT
log.Println(v)
AssertEqual(t, ok, true, "Set-Cookie shold be available")
AssertEqual(t, checkRecorderCookieBiukopCL(v), true, "cookie value should be valid")

//compare body content
pixel, err := crmpixelImage()
AssertEqual(t, err, nil, "pixel image should have no error")
m, err := ioutil.ReadAll(rr.Body)
AssertEqual(t, testEq(pixel, m), true, "pixel image should be the same")

}

func checkRecorderCookieBiukopCL(v []string) bool {
// Copy the Cookie over to a new Request
request := &http.Request{Header: http.Header{"Cookie": v}}

// Extract the dropped cookie from the request.
cookie, err := request.Cookie("biukop_cl")

valid, _ := isValidCookieBiukopCL(cookie.Value)
return err == nil && valid
}

func buildReqCrmPixel() (req *http.Request) {
req, err := http.NewRequest("GET", "/crmpixel.png", nil)
if err != nil {
log.Fatal(err)
}
//buildReqCommonSignature(req, IntraAPIConfig.CRMSecrete)
buildReqCommonHeader(req)
return req
}

//compare two byte slice
func testEq(a, b []byte) bool {

if a == nil && b == nil {
return true
}

if a == nil || b == nil {
return false
}

if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}

+ 1
- 1
main.go Parādīt failu

@@ -63,7 +63,7 @@ func setupHTTPHandler() {
http.HandleFunc("/profile_newly_register", initialRegistrationHandler)
http.HandleFunc("/iapi/getAccessToken", supplyAccessToken)
http.HandleFunc("/iapi/createWechatQr", iapiCreateWechatQrCode)
http.HandleFunc("/crmpixel", crmpixel) //tracking pixel.
http.HandleFunc("/crmpixel.png", crmpixel) //tracking pixel.
http.ListenAndServe(":65500", nil)
}


+ 6
- 3
server.go Parādīt failu

@@ -185,15 +185,18 @@ func calculateSignature(timestamp, nonce, token string) (signature string) {
strs := []string{token, timestamp, nonce}
sort.Strings(strs)
s := strings.Join(strs, "")
signature = strSHA1(s)
return
}

func strSHA1(s string) string {
//calculate sha1
h := sha1.New()
h.Write([]byte(s))
calculated := fmt.Sprintf("%x", h.Sum(nil))
signature = calculated
return
}
return calculated

}
func timestampTooOldStr(timestamp string) bool {
ts, err := strconv.Atoi(timestamp)
if err != nil {

Notiek ielāde…
Atcelt
Saglabāt