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": "\ufffd\u0002\ufffd\u001eu\ufffd\u001c\ufffd\u0013m\ufffdM\\\ufffd\ufffd\u0011",
    "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 级别的路由使用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏李蔚蓬的专栏

1.Android系统源代码目录与系统目录

想要看完整个Android的源代码,需要懂C、懂脚本、懂Java、软硬兼通。所以一般情况下,我们了解源代码的框架结构,出了问题知道从哪里着手解决就可以了。这就好...

5622
来自专栏Coding迪斯尼

从0到1用java再造tcpip协议栈:实现ARP协议层

经过前两节的准备,我们完成了数据链路层,已经具备了数据包接收和发送的基础设施,本机我们在此基础上实现上层协议,我们首先从实现ARP协议开始。先简单认识一下ARP...

1972
来自专栏潇涧技术专栏

Art of Android Development Reading Notes 10

《Android开发艺术探索》读书笔记 (10) 第10章 Android的消息机制

651
来自专栏张善友的专栏

Contact Manager Web API 示例[4] 异常处理(Exception Handling)

联系人管理器web API是一个Asp.net web api示例程序,演示了通过ASP.NET Web API 公开联系信息,并允许您添加和删除联系人,示例地...

1957
来自专栏IMWeb前端团队

Flash as3 socket编程入门

什么是socket? 所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求...

21910
来自专栏刘晓杰

Okhttp3 Interceptor

3557
来自专栏landv

烽火2640路由器命令行手册-08-服务质量配置命令

要配置当前策略映像所用的类型映像的名字,所占带宽和队列上限,可使用策略映像配置态中的配置命令class,使用本命令的no形式从策略映像中删除某个类型映像或恢复参...

882
来自专栏源哥的专栏

基于linux的嵌入IPv4协议栈的内容过滤防火墙系统(5)-包过滤模块和内容过滤模块所采用的各种技术详述

3。1 module编程 module可以说是 Linux 的一大革新。有了 module 之后,写 device driver 不再是一项恶梦,修改 ker...

1163
来自专栏大内老A

[WCF的Binding模型]之三:信道监听器(Channel Listener)

信道管理器是信道的创建者,一般来说信道栈的中每个信道对应着一个信道管理器。基于不同的消息处理的功能,将我们需要将相应的信道按照一定的顺序能组织起来构成一个信道栈...

2065
来自专栏Android 研究

Android Handler机制11之Handler机制总结

经过上面的思考,大家是不是发现和其实我们Handler的机制基本上一致。Looper负责轮询;Message代表消息,为了区别对待,用what来做为标识符,wh...

1K1

扫码关注云+社区

领取腾讯云代金券