网站建设咨询公司地址,高邮城乡建设局网站,【网站建设,建设机械网站平台【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 【REST2SQL】07 GO 操作 Mysql 数据库 【RE…【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 【REST2SQL】07 GO 操作 Mysql 数据库 【REST2SQL】08 日志重构增加输出到文件log.txt 【REST2SQL】09 给Go的可执行文件exe加图标和版本信息等 【REST2SQL】10 REST2SQL操作指南 【REST2SQL】11 基于jwt-go生成token与验证 【REST2SQL】11 基于jwt-go生成token与验证的Token生成和验证合并到【REST2SQL】
1 Rest2sql目录下新建token子目录 Rest2sql目录下新建token子目录 拷贝 【REST2SQL】11 基于jwt-go生成token与验证 的mytoken.go mytoken.go改名为 token.go
2 token.go的代码重构 包名改为token 屏蔽或删除 main()入口函数 重构全局变量都改为外部不可见即变量名改为首字母改为小写即可 只暴露生成token函数GenerateTokenHandler()和验证token函数ValidateTokenHandler() 暴露函数第二个参数重构
重构完成的代码如下
package tokenimport (crypto/randencoding/jsonfmtlognet/httptimejwt github.com/dgrijalva/jwt-go
)// 定义Token的Claims
type customClaims struct {userid string json:useridpasswd string json:passwdjwt.StandardClaims
}// 定义Token相关变量
var (uid string BLMa //用户名pwd string 5217 //密码key string token //默认密钥服务启动时会修改iss string guwuy //签发者timeStamp int64 time.Now().Unix() // 时间戳用于定期更新密钥keytimeSecond int64 60 * 60 * 24 * 7 //一周时间的秒数用于7天修改一次KeytimeExpires int64 60 * 60 * 8 // Token 过期时间 秒数8小时
)// generateRandomString 生成一个指定长度的随机字符串
func generateRandomString(length int) (string, error) {const letters abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZbytes : make([]byte, length)if _, err : rand.Read(bytes); err ! nil {return , err}for i, b : range bytes {bytes[i] letters[b%byte(len(letters))]}return string(bytes), nil
}// 定期生成随机Key
func generateRandomKey() {//当前时间戳timestamp : time.Now().Unix()if (timestamp-timeStamp timeSecond) || len(key) 10 {// 修改KeyKey, err : generateRandomString(16)if err ! nil {log.Fatal(err)}timeStamp timestamp // 更新Key修改的时间戳// 打印时间戳fmt.Println(timeStamp :, timeStamp, time.Unix(timeStamp, 0))fmt.Println(Random String:, Key)}
}// 生成新的Token
func generateToken(userid string) (string, error) {// 设置Claimsclaims : customClaims{userid: userid,passwd: pwd,StandardClaims: jwt.StandardClaims{ExpiresAt: time.Now().Add(time.Second * 5217).Unix(), // 设置过期时间Issuer: iss, // 设置签发者},}// 创建Tokentoken : jwt.NewWithClaims(jwt.SigningMethodHS256, claims)// 定期生成随机KeygenerateRandomKey()// 签名Token这里使用硬编码的密钥实际生产环境中应使用更安全的密钥管理方式signedToken, err : token.SignedString([]byte(key))if err ! nil {return , err}return signedToken, nil
}// 验证Token
func validateToken(tokenString string) (*customClaims, error) {// 解析Tokentoken, err : jwt.ParseWithClaims(tokenString, customClaims{}, func(token *jwt.Token) (interface{}, error) {// 验证Token的签名这里使用硬编码的密钥return []byte(key), nil})if claims, ok : token.Claims.(*customClaims); ok token.Valid {return claims, nil}return nil, err
}// HTTP处理函数生成Token
func GenerateTokenHandler(w http.ResponseWriter, uid_pwd map[string]string) {//请求参数,实际情况下这里可能从请求参数或身份验证过程中获取uid uid_pwd[Userid]pwd uid_pwd[Passwd]// 这里加uidpwd的数据库校验token, err : generateToken(uid)if err ! nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}w.Header().Set(Content-Type, application/json)json.NewEncoder(w).Encode(map[string]string{token: token,})
}// HTTP处理函数验证Token
func ValidateTokenHandler(w http.ResponseWriter, tokenString string) {claims, err : validateToken(tokenString)if err ! nil {http.Error(w, err.Error(), http.StatusUnauthorized)return}w.Header().Set(Content-Type, application/json)json.NewEncoder(w).Encode(map[string]interface{}{userid: claims.userid,expires: claims.ExpiresAt,})
}// // main入口
// func main() {
// // 检查并生成Key
// GenerateRandomKey()// // Token 路由
// http.HandleFunc(/generate-token, generateTokenHandler)
// // Http://localhost:8080/generate-token?useridblmapasswd5217
// // curl Http://localhost:8080/generate-token?useridblma%26passwd5217
// http.HandleFunc(/validate-token, validateTokenHandler)
// //curl http://localhost:8080/validate-token -H Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiI5OTk4IiwicGFzc3dkIjoiODk5OSIsImV4cCI6MTcwOTcyMDU0MSwiaXNzIjoiZ3V3dXkifQ.UXiW-cgnDZfGUmLtv_yme6gzFZ9XDiKaNATIdFzJ2fY// fmt.Println(Starting Token server ...)
// fmt.Println(Http://localhost:8080/generate-token?useridpasswd)
// fmt.Println(curl http://localhost:8080/validate-token -H \Authorization:token\)
// log.Fatal(http.ListenAndServe(:8080, nil))
// }
3 rest2sql.go的 handler() 增加token访问路由
重构的核心代码如下 请求路径错误提示代码
// 2请求路径Pathreq[Path] r.URL.Pathpath : strings.Split(r.URL.Path, /)if len(path) 3 {w.Write([]byte(400 Bad Request错误请求。请尝试/rest/xxx or /sql/xxx or /TOKEN/xxx))return}允许的请求路径代码
// 3 请求类型REST or SQL or Tokenrors : strings.ToUpper(fmt.Sprint(path[1]))// 支持的请求类型if !(rors REST || rors SQL || rors TOKEN) {w.Write([]byte(400 Bad Request错误请求。请尝试/REST/xxx or /SQL/xxx or /TOKEN/xxx))return}请求头token结构代码
// 8 请求头 Authorizationreq[Authorization] r.Header.Get(Authorization) // 假设Token在Authorization头中请求参数增加userid和passw代码
// 9 请求参数query : r.URL.Query()req[Userid] query.Get(userid) // 登录用户req[Passwd] query.Get(passwd) // 登录密码3 dothing.go代码重构
分支代码case TOKEN:// Token 生成与校验doTOKEN(w, req)doTiken函数代码
// 根据请求参数执行不同的TOKEN操作 ///
func doTOKEN(w http.ResponseWriter, req map[string]interface{}) {// token操作 generate or validateresToken : strings.ToLower(req[ResName].(string))switch resToken {case generate-token:// w.Write([]byte(generate-token))var uid_pwd map[string]string make(map[string]string)uid_pwd[Userid] req[Userid].(string)uid_pwd[Passwd] req[Passwd].(string)token.GenerateTokenHandler(w, uid_pwd)// http://127.0.0.1:5217/TOKEN/generate-token?userid9998passwd8999case validate-token://w.Write([]byte(validate-token))var tokenString string req[Authorization].(string)token.ValidateTokenHandler(w, tokenString)// curl http://localhost:5217/token/validate-token -H Authorization:token}
}4 实操演练
Setp 1 启动服务 Step 2 生成Token
http://127.0.0.1:5217/TOKEN/generate-token?userid9998passwd8999Step 3 验证Token
curl http://localhost:5217/token/validate-token -H Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDk4Njk0OTEsImlzcyI6Imd1d3V5In0.7CLaQKNXZOhnirLfOb_1meYYnc6KVDkXUhrxbfvYgKwStep 4 服务日志 本文完。