func TestControlSign(t *testing.T) { param := map[string]interface{}{ "token": "000000000", "service": "service1", "cmd": "reboot", } devId := "device1" accessKey := "820b4376bad3486199e13a7ada104106" secretKey := "EwYmYyqdChgitRcrInBg" date := time.Now().Format(time.RFC1123) body, _ := json.Marshal(param) req, _ := http.NewRequest("POST", fmt.Sprintf("http://127.0.0.1:8080/api/v1/devices/%s", devId), bytes.NewBuffer(body)) sign := utils.Sign(secretKey, "POST", req.URL.Path, body, date, nil) //req, _ := http.NewRequest("POST", "http://push.scloud.letv.com/api/v1/message", bytes.NewBuffer(body)) req.Header.Add("Date", date) req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", fmt.Sprintf("LETV %s %s", accessKey, sign)) reqDump, _ := httputil.DumpRequest(req, true) t.Logf("HTTP Request:\n%s", reqDump) client := &http.Client{} resp, err := client.Do(req) if err != nil { t.Errorf("request err: %s", err) t.FailNow() } respDump, _ := httputil.DumpResponse(resp, true) t.Logf("HTTP Response:\n%s", respDump) if resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusBadRequest { t.FailNow() } }
func TestPushSign(t *testing.T) { param := map[string]interface{}{ "msg_type": 1, "push_type": 1, "content": "just a test", } accessKey := "appid_b515357337f7415ab9275df7a3f92d94" secretKey := "appsec_ckeasUHYFkAvEitqagAr" date := time.Now().Format(time.RFC1123) body, _ := json.Marshal(param) req, _ := http.NewRequest("POST", "http://127.0.0.1:8080/api/v1/message", bytes.NewBuffer(body)) sign := utils.Sign(secretKey, "POST", req.URL.Path, body, date, nil) //req, _ := http.NewRequest("POST", "http://push.scloud.letv.com/api/v1/message", bytes.NewBuffer(body)) req.Header.Add("Date", date) req.Header.Add("Authorization", fmt.Sprintf("LETV %s %s", accessKey, sign)) reqDump, _ := httputil.DumpRequest(req, true) t.Logf("HTTP Request:\n%s", reqDump) client := &http.Client{} resp, err := client.Do(req) if err != nil { t.Errorf("request err: %s", err) t.FailNow() } respDump, _ := httputil.DumpResponse(resp, true) t.Logf("HTTP Response:\n%s", respDump) if resp.StatusCode != http.StatusOK { t.FailNow() } }
func delApp(w http.ResponseWriter, r *http.Request) { authstr := r.Header.Get("Authorization") date := r.Header.Get("Date") auth := strings.Fields(authstr) if len(auth) < 3 { errResponse(w, ERR_AUTHORIZE, "invalid 'Authorization' header", 400) return } appid := auth[1] sign := auth[2] b, err := storage.Instance.HashGet("db_apps", appid) if err != nil { errResponse(w, ERR_INTERNAL, "storage I/O failed", 500) return } if b == nil { errResponse(w, ERR_NOT_EXIST, "app not exist", 400) return } var rawapp storage.RawApp json.Unmarshal(b, &rawapp) body, _ := ioutil.ReadAll(r.Body) if sign != ADMIN_SIGN { if utils.Sign(rawapp.AppSec, r.Method, r.URL.Path, body, date, r.Form) != sign { errResponse(w, ERR_SIGN, "check sign failed", 400) return } } if _, err = storage.Instance.HashDel("db_apps", appid); err != nil { errResponse(w, ERR_INTERNAL, "del 'db_apps' failed", 500) return } if _, err = storage.Instance.HashDel("db_packages", rawapp.Pkg); err != nil { errResponse(w, ERR_INTERNAL, "del 'db_packages' failed", 500) return } var response Response response.ErrNo = 0 b, _ = json.Marshal(response) fmt.Fprintf(w, string(b)) }
// // check the signature of the request // the signature calulation need to read full content of request body // the body is then put into the request.Env["body"] and passed to // the next handler // func AuthMiddlewareFunc(h rest.HandlerFunc) rest.HandlerFunc { return func(w rest.ResponseWriter, r *rest.Request) { controlAK := "820b4376bad3486199e13a7ada104106" secretKey := "EwYmYyqdChgitRcrInBg" authstr := r.Header.Get("Authorization") auth := strings.Fields(authstr) if len(auth) != 3 { rest.Error(w, "Invalid 'Authorization' header", http.StatusBadRequest) return } accessKey := auth[1] sign := auth[2] if accessKey != controlAK { rest.Error(w, "Invalid AccessKey", http.StatusForbidden) return } dateStr := r.Header.Get("Date") date, err := time.Parse(time.RFC1123, dateStr) if err != nil { rest.Error(w, "Invalid 'Date' header", http.StatusBadRequest) log.Warnf("Unknown 'Date' header: %s", err.Error()) return } log.Debugf("Date header: %s", date.String()) body, _ := ioutil.ReadAll(r.Body) r.ParseForm() if sign != "supersignature" { //TODO: remove this if utils.Sign(secretKey, r.Method, "/api/v1"+r.URL.Path, body, dateStr, r.Form) != sign { rest.Error(w, "Signature varification failed", http.StatusForbidden) return } } r.Env["body"] = body h(w, r) } }
func addMessage(w http.ResponseWriter, r *http.Request) { authstr := r.Header.Get("Authorization") date := r.Header.Get("Date") auth := strings.Fields(authstr) if len(auth) < 3 { errResponse(w, ERR_AUTHORIZE, "invalid 'Authorization' header", 400) return } appid := auth[1] sign := auth[2] // load app info b, err := storage.Instance.HashGet("db_apps", appid) if err != nil { errResponse(w, ERR_INTERNAL, "get 'db_apps' failed", 500) return } if b == nil { errResponse(w, ERR_NOT_EXIST, "app not exist", 400) return } var rawapp storage.RawApp json.Unmarshal(b, &rawapp) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Errorf("read request body failed: (%s) (%s)", r.Body, err) errResponse(w, ERR_BAD_REQUEST, "failed read request body", 400) return } // check sign if sign != ADMIN_SIGN { if utils.Sign(rawapp.AppSec, r.Method, r.URL.Path, body, date, r.Form) != sign { errResponse(w, ERR_SIGN, "check sign failed", 400) return } } // decode JSON body msg := storage.RawMessage{} if err := json.Unmarshal(body, &msg); err != nil { log.Errorf("JSON decode failed: (%s) (%s)", body, err) errResponse(w, ERR_BAD_REQUEST, "json decode body failed", 400) return } msg.AppId = appid // check message format ok, desc := checkMessage(&msg) if !ok { errResponse(w, ERR_INVALID_PARAMS, desc, 400) return } msgid := getMsgID() if msgid == 0 { errResponse(w, ERR_INTERNAL, "no avaiable msgid", 500) return } msg.MsgId = msgid if msg.Options.TTL < 0 { // send immediatly msg.Options.TTL = 0 } else if msg.Options.TTL == 0 { msg.Options.TTL = 86400 // default } var response Response response.ErrNo = 0 response.Data = map[string]int64{"msgid": msgid} msg.CTime = time.Now().Unix() msgBox <- msg b, _ = json.Marshal(response) fmt.Fprintf(w, string(b)) storage.Instance.AppStatsPushApi(appid) }
func postNotify(w http.ResponseWriter, r *http.Request) { var response Response response.ErrNo = 10000 if r.Method != "POST" { http.Error(w, "Method not allowed", 405) return } data := PostNotifyData{} if err := json.NewDecoder(r.Body).Decode(&data); err != nil { response.ErrNo = 10001 response.ErrMsg = fmt.Sprintf("invalid notification data, %s", err) b, _ := json.Marshal(response) fmt.Fprintf(w, string(b)) return } if len(data.Notices) > conf.Config.Notify.MaxNotices { response.ErrNo = 10002 response.ErrMsg = "notification msgs over limit" b, _ := json.Marshal(response) fmt.Fprintf(w, string(b)) return } results := make(map[int64]chan *Result) for _, n := range data.Notices { if n.Id == 0 { log.Warnf("there's a notice without id") continue } log.Infof("send notice[%d]", n.Id) rchan := make(chan *Result) results[n.Id] = rchan go func(n Notice) { if !checkNotice(n) { rchan <- &Result{ Error: fmt.Errorf("invalid notice, please check notice's items with wiki"), Data: nil, } return } d := n.PushMsg d.PushType = PUSH_WITH_UID d.AppId = n.AppId log.Infof("get uids with notice[%d]", n.Id) err, resp := callThirdPartyIf("GET", fmt.Sprintf("%s%s", conf.Config.Notify.SubUrl, n.Tags), nil, nil) if err != nil { rchan <- &Result{ Error: err, Data: nil, } return } var uids []string getUids(resp, &uids) d.PushParams.UserId = uids data, _ := json.Marshal(d) log.Infof("push msgs with notice[%d]", n.Id) path := strings.SplitN(conf.Config.Notify.PushUrl, "/", 4) date := time.Now().UTC().String() sign := utils.Sign(n.AppSec, "POST", fmt.Sprintf("/%s", path[3]), data, date, nil) header := map[string]string{ "Content-Type": "application/json", "Date": date, "Authorization": fmt.Sprintf("LETV %s %s", n.AppId, sign), } err, resp = callThirdPartyIf("POST", conf.Config.Notify.PushUrl, bytes.NewBuffer(data), &header) rchan <- &Result{ Error: err, Data: resp, } }(n) } for nid, c := range results { select { case result := <-c: log.Infof("sent notice[%d]", nid) if result.Error != nil { response.Data.UnSent = append(response.Data.UnSent, ResponseItem{Id: nid, Data: fmt.Sprintf("%s", result.Error)}) } else { response.Data.Sent = append(response.Data.Sent, ResponseItem{Id: nid, Data: result.Data}) } case <-time.After(conf.Config.Notify.Timeout * time.Second): log.Infof("notify timeout %d", nid) response.Data.UnSent = append(response.Data.UnSent, ResponseItem{Id: nid, Data: fmt.Sprintf("notify timeout")}) } } b, _ := json.Marshal(response) fmt.Fprintf(w, string(b)) }