a common tool for providing api to third-party users
theoretically the tool is compatible with all kinds of web framework
and iris
and gin
is the recommend web framework.
if you use the default sql implementation, you should create a table first of course, you can define your own table as long as you point out the right way to get your actual secret
CREATE TABLE `app` (
`app_key` varchar(32) NOT NULL,
`app_secret` varchar(128) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`app_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
another way for you to get the secret is you can implement the interface here
// the interface to get the secret
type SecretKeeper interface {
GetSecret() (string, error)
}
create a middle ware for some web framework
// create a middle ware for iris
func OpenApiHandler(ctx iris.Context) {
//sign header? to prevent header being modified by others
// openapi.SignHeader(true)
req := ctx.Request()
// you can put the key somewhere in the header or url params
r, err := openapi.CheckValid(req,
// default implementation is via sql, to fetch the secrect
openapi.SqlSecretKeeper{
Db: store.GetDb(),
TableName: "app", // the name of table where you store all your app keys and secretcs
KeyCol: "app_key", // the column name of the app keys
SecretCol: "app_secret", // the column name of the app secrets
})
logError(err)
if r {
// verfy success, continue the request
ctx.Next()
} else {
// verify fail, stop the request and return
ctx.Text(err.Error())
ctx.StopExecution()
return
}
}
use it on some kind of api groups
// use the middle ware somewhere
// so all the apis under this group should be
// called with signed result and app key
openApiGroup := app.Party("/open")
openApiGroup.Use(OpenApiHandler)
{
openApiGroup.Get("/app", func(ctx iris.Context) {
ctx.Text("success")
})
}
func GetSomeAPIResult() {
client := openapi.DefaultClient("key....", "a9f83xa3sjh7xad")
result, err := client.Get("/api/testdata")
result, err := client.Post("/api/testdata", "post body")
// ...
// result is the data from remote api, and the remote api is enforced
// by this very open api handler
}
- get current time in millis and append it to the existing parameters
?time=1553759639794
- add
app_key
param to your url params - take out all the headers and params and sort them
- connect the sorted params to a string use
x=y&
to one string - sign the connected string and append the param
&sign={sign_result}
to your url parameter - send the request
then you will succeed.
we only provide sha256 as the sign method of the string content
// sign with sha 256
func Sign(content, key string) string {
h := sha256.New()
h.Write([]byte(content + key))
return fmt.Sprintf("%x", h.Sum(nil))
}
sort order is ascending
func buildParams(params Pairs) string {
sort.Sort(params)
var result string
for _, v := range params {
r := v.Key + "=" + v.Value + "&"
result += r
}
return result
}