package main import ( "fmt" // "bytes" // "encoding/json" // "io/ioutil" "log" "net/http" "strings" "time" jwt "github.com/dgrijalva/jwt-go" "github.com/go-macaron/binding" "gopkg.in/macaron.v1" ) const ( JWT_Secret = "jwt-Dashoo-1705" JWT_Issuer = "dashoo.cn" JWT_Audience = "dashoo" JWT_Expires = 24 * 60 * 60 // 24h ) type MyCustomClaims struct { // This will hold a users username after authenticating. // Ignore `json:"username"` it's required by JSON Username string `json:"username"` // This will hold claims that are recommended having (Expiration, issuer) jwt.StandardClaims } func main() { m := macaron.Classic() m.Use(macaron.Recovery()) m.Use(macaron.Renderer()) m.Use(macaron.Static("front_end")) m.Get("/", defaultGet) //前端框架使用的API m.Post("/api/auth/login", binding.Json(User{}), loginPost) m.Post("/api/tokens", binding.Json(User{}), genTokenPost) // 生成JWT token m.Get("/api/tokens", checkTokenGet) // 检验JWT token是否有效 m.Get("/api/users/me", getCurUserGet) // 获取登录用户信息 log.Println("Server is running...") log.Println(http.ListenAndServe("0.0.0.0:4000", m)) } // 返回的json body 映射结构 type User struct { Username string `json:"username"` Password string `json:"password"` } type ResultUser struct { Name string `json:"name"` UserName string `json:"username"` Slug string `json:"slug"` } type ResponseUser struct { User ResultUser `json:"user"` } // 用户登录处理 func loginPost(ctx *macaron.Context, user User) { // request data body 通过binding自动解析到映射结构 username := user.Username // todo 处理登录验证 // 返回json数据 ctx.JSON(200, map[string]interface{}{ "user": username, "role": "admin", }) } // 生成JWT token func genTokenPost(ctx *macaron.Context, user User) { fmt.Println("un=", user.Username) claims := MyCustomClaims{ user.Username, jwt.StandardClaims{ NotBefore: int64(time.Now().Unix()), ExpiresAt: int64(time.Now().Unix() + JWT_Expires), Issuer: JWT_Issuer, }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) signedToken, err := token.SignedString([]byte(JWT_Secret)) if err != nil { log.Println(err) // return 401 } ctx.JSON(201, map[string]interface{}{ "token": signedToken, }) } // 检验JWT token是否有效 func checkTokenGet(ctx *macaron.Context) { // fmt.Println(ctx.Req.Request.Header["Authorization"]) authString := ctx.Req.Request.Header["Authorization"][0] auths := strings.Split(authString, " ") if len(auths) != 2 || auths[0] != "Bearer" { log.Println("AuthString invalid:", authString) // return 401 } signedToken := auths[1] fmt.Println("signedToken=", signedToken) token, err := jwt.ParseWithClaims(signedToken, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(JWT_Secret), nil }) if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid { fmt.Printf("%v %v", claims.Username, claims.StandardClaims.ExpiresAt) ctx.JSON(200, map[string]interface{}{ "msg": "Token is validated.", }) } else { fmt.Println(err) // return 401 } // ctx.JSON(200, map[string]interface{}{ // "user": username, // "role": "admin", // }) } func getCurUserGet(ctx *macaron.Context) ResponseUser { authString := ctx.Req.Request.Header["Authorization"][0] auths := strings.Split(authString, " ") if len(auths) != 2 || auths[0] != "Bearer" { log.Println("AuthString invalid:", authString) // return 401 } signedToken := auths[1] fmt.Println("signedToken=", signedToken) token, err := jwt.ParseWithClaims(signedToken, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(JWT_Secret), nil }) if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid { fmt.Printf("%v %v", claims.Username, claims.StandardClaims.ExpiresAt) //to do get user user := ResultUser{} user.Name = claims.Username user.UserName = claims.Username user.Slug = "dashoo" responseUser := ResponseUser{} responseUser.User = user return responseUser // ctx.JSON(200, map[string]interface{}{ // "username": claims.Username, // }) } else { fmt.Println(err) return ResponseUser{} // return 401 } } func defaultGet(ctx *macaron.Context) { ctx.Data["method"] = "(Get)" ctx.HTML(200, "default") }