• XGoServer 一个基础性、模块完整且安全可靠的服务端框架


    作者:林冠宏 / 指尖下的幽灵

    掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

    博客:http://www.cnblogs.com/linguanh/

    GitHub : https://github.com/af913337456/

    腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities


    一个基础性、模块完整且安全可靠的服务端框架

    开源地址:https://github.com/af913337456/XGoServer

    第一版介绍文章:基于 xorm 的服务端框架 XGoServer


    新添加模块

    • 自定义路由接口
    • Token模块,jwt
    • 加解密模块,cipher-AES,可自行拓展其他
    • 各模块对应的单元测试例子

    共具备的

    • 自定义路由接口
    • Token模块,jwt
    • 加解密模块,cipher-AES,可自行拓展其他
    • 日志模块,alecthomas/log4go
    • 路由模块,gorilla/mux
    • 硬存储 / 软存储 采用 xorm 框架
    • 服务端通用的输出数据结构的整合,例如 json
    • 各模块对应的单元测试例子

    自定义路由接口

    requireToken 标识该路由是否需要 token 验证

    TokenData 是我们要组合到 token 里面的数据结构 struct

    type Context struct {
    	TokenData TokenData
    	TokenStr  string  	`json:"tokenStr"`
    	IpAddress string  	`json:"ipAddress"`  // client 的 ip
    	RoutePath string  	`json:"routePath"`
    }
    type XHandler struct {
    	handleFunc   func(*Context, http.ResponseWriter, *http.Request)
    	requireToken bool
    }
    func (x XHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
    	tokenStr := r.Header.Get(TokenAuth)
    	c := &Context{}
    	c.IpAddress = util.GetIpAddress(r)
    	c.RoutePath = r.URL.Path
    	if x.requireToken {
    		tokenData,err := ParseToken(tokenStr) // 使用 token 模块进行解析
    		if err != nil {
    			util.RenderJson(w,util.GetCommonErr(err.Error()))
    			return
    		}
    		c.TokenData = *tokenData
    		c.TokenStr  = tokenStr
    		// util.RenderJson(w,c)
    		x.handleFunc(c,w,r)
    		return
    	}
    	// 不需要 token
    	util.LogInterface(c)
    	x.handleFunc(c,w,r)
    }
    
    

    用法

    • router.Handle("/get1",core.ApiNormalHandler(getToken)).Methods("GET")
    • router.Handle("/get2",core.ApiRequestTokenHandler(handleToken)).Methods("GET")
    • 搭配使用:
    router.Handle("/getToken",core.ApiNormalHandler(getToken)).Methods("GET")
    router.Handle("/handleToken",core.ApiRequestTokenHandler(handleToken)).Methods("GET")
    router.HandleFunc("/enc",encOutput).Methods("GET")
    router.HandleFunc("/dec",decOutput).Methods("POST")
    

    例子集合

    • 直接输出一条 json 给客户端
    • 登陆成功生成 token 返回
    • 直接输出解析后的 Context
    • 加密输出
    • 与数据库交互 ----- important

    直接输出一条 json 给客户端

    func main()  {
        router := new (mux.Router)
        router.HandleFunc("/",test2).Methods("GET")
        core.HttpListen(router)
    }
    func test2(w http.ResponseWriter,r *http.Request)  {
        // 非常简单的例子, 操作放在内部 , 可以使用 request 来获取自己的参数,再直接组织输出
        core.HandlerMapWithOutputJson(w, func() map[string]interface{} {
        	m :=  map[string]interface{}{}
        	m["msg"] = "blow me a kiss"
        	return m
        })
    }
    // 结果 : {"msg":"blow me a kiss"}
    

    登陆成功生成 token 返回

    token 是具备过期时间的,皆可自定义

    func getToken(c *core.Context, w http.ResponseWriter, r *http.Request)  {
    	core.HandlerMapWithOutputJson(w, func() map[string]interface{} {
    		tokenStr,err := core.BuildDefaultToken(func(tokenData *core.TokenData) {
    			tokenData.UserId = "123456"  // 用户 id
    			tokenData.Roles  = "normal"  // 用户角色
    		})
    		if err != nil {
    			return util.GetCommonErr(err.Error())
    		}
    		return util.GetCommonSuccess(tokenStr)
    	})
    }
    结果:
    {
        "msg": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDU2Iiwicm9sZXMiOiJub3JtYWwiLCJwcm9wcyI6bnVsbCwiZXhwIjoxNTE5MDA2Njg4LCJpYXQiOjE1MTkwMDY2Mjh9.NsBsQ3xpOJNZUXO5Dc-Yk4p4m6p4EeDWgEfc5BaNKd4",
        "ret": "success"
    }
    

    直接输出解析后的 Context

    tokenStr 是 Context 一变量

    handleToken 方法对于的是 ApiRequestTokenHandler

    func handleToken(c *core.Context, w http.ResponseWriter, r *http.Request)  {
    	util.RenderJson(w,context)
    }
    

    输出加密的数据

    tokenStr 是 Context 一变量

    handleToken 方法对于的是 ApiRequestTokenHandler

    type IEncrypt interface {
    	AesEncrypt(origData, key []byte) ([]byte, error)   // 加密
    	AesDecrypt(encrypted, key []byte) ([]byte, error)  // 解密
    }
    // 加密输出
    func encOutput(w http.ResponseWriter, r *http.Request)  {
    	core.HandlerMapWithOutputJson(w, func() map[string]interface{} {
    		d := "狗年平安"
    		aes := encrypt.DefaultAES{}
    		return util.GetCommonSuccess(aes.AesEncryptStr(d))
    	})
    }
    输出:
    {
        "msg": "ufffdu0002ufffdu001euufffdu001cufffdu0013mufffdM\ufffdufffdu0011",
        "ret": "success"
    }
    

    与数据库交互

    func test3(w http.ResponseWriter,r *http.Request)  {
    	core.HandlerMapWithOutputJson(w, func() map[string]interface{} {
    		// 插入一条评论
    		item := &model.Comment{
    			Id	:util.NewId(),         // 评论 id
    			UserId	:"123456",             // 评论人 id
    			Name	:"LinGuanHong",        // 评论人名称
    			Content	:"hello word",         // 评论内容
    		}
    		affect,_ := core.Engine.Insert(item)  // 执行插入,传入 struct 引用
    		m :=  map[string]interface{}{}
    		if affect > 0 {
    			m["ret"] = "insert success"
    			comments := make([]model.Comment, 0)
    			core.Engine.Find(&comments)   // select 出来,获取所有评论输出
    			m["msg"] = comments
    		}else{
    			m["ret"] = "insert failed"
    		}
    		return m
    	})
    }
    
    输出的结果是:
    {
      "msg": [
        {
          "id": "1kubpgh9pprrucy11e456fyytw",
          "UserId": "123456",
          "name": "LinGuanHong",
          "content": "hello word"
        }
      ],
      "ret": "insert success"
    }
    
    

    上述的功能结合使用,便可做到牢固的安全性。此外,可以再结合 https 级别的路由使用。

  • 相关阅读:
    Python:判断文本中的用户名在数据库中是否存在,存在返回1,不存在返回0
    Mongodb创建修改用户权限
    web开发一些常用的工具类的网站
    python linux交互模块(paramiko、fabric与pexpect)
    python内建模块详解
    python笔记_01_打开文件读取一行的最好方法
    轻量级RPC设计与实现第二版
    轻量级RPC设计与实现第一版
    Dubbo-服务注册中心之AbstractRegistry
    dubbo之心跳机制
  • 原文地址:https://www.cnblogs.com/linguanh/p/8453685.html
Copyright © 2020-2023  润新知