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

掘金: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 级别的路由使用。

XGoServer 一个基础性、模块完整且安全可靠的服务端框架的更多相关文章

  1. 基于 xorm 的服务端框架 XGoServer

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  2. 无框架完整搭建安卓app及其服务端(一)

    技术背景: 我的一个项目做的的是图片处理,用 python 实现图片处理的核心功能后,想部署到安卓app中,但是对于一个对安卓和服务器都一知半解的小白来说要现学的东西太多了. 而实际上,我们的项目要求 ...

  3. 一个3D的多人在线游戏, 服务端 + 客户端 【转】

    最近学院组织了一个实训,要求是利用Socket通信和D3D的知识, 写一个多人在线的游戏, 服务端是在linux下, 客户是在Windows下: 写这个的目的是想让大家给我找错, 欢迎大家的意见.我的 ...

  4. 基于NIO的同步非阻塞编程完整案例,客户端发送请求,服务端获取数据并返回给客户端数据,客户端获取返回数据

    这块还是挺复杂的,挺难理解,但是多练几遍,多看看研究研究其实也就那样,就是一个Selector轮询的过程,这里想要双向通信,客户端和服务端都需要一个Selector,并一直轮询, 直接贴代码: Ser ...

  5. 用.Net打造一个移动客户端(Android/IOS)的服务端框架NHM(四)——Android端Http访问类(转)

    本章目的 在上一章中,我们利用Hibernate Tools完成了Android Model层的建立,依赖Hibernate Tools的强大功能,自动生成了Model层.在本章,我们将继续我们的项目 ...

  6. qq2013 java版(完整工程源码 包含服务端 oracle数据库)毕业设计有用

    /** * 初始化组件 */ private void initComponent() { //提示面板 errorTipPane = new ErrorTipPane(); // 主面板 mainP ...

  7. 适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

    本文由“yuanrw”分享,博客:juejin.im/user/5cefab8451882510eb758606,收录时内容有改动和修订. 0.引言 站长提示:本文适合IM新手阅读,但最好有一定的网络 ...

  8. 【翻译】DotNetMQ: 一个.NET版完整的消息队列系统

    在一个大型的分布式系统中,消息队列是不可缺少的中间件,能很好的解决异步消息.应用解耦.均衡并发等问题.在.net中,偶然发现一个效率不错.安全可靠.功能齐全的消息组件,忍不住翻译过来,供大家快速预览. ...

  9. IIS 错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    导致这种问题的原因是ASP.NET没有成功注册到IIS中,很有可能是先安装.Net Framework,然后安装IIS.为了避免此问题发生,要先安装IIS再安装.Net Framework. 解决方案 ...

随机推荐

  1. echarts图表里label文字过长换行的方法

    在做一些图标时,有时会出现显示文字过长的问题,需要将其按照指定的字数换行,像下图这样 而echarts没有提供换行的方法,但是可以使用fomatter方法进行设置,代码如下 formatter: fu ...

  2. 【干货】平安打卡神器E行销刷脸考勤破解,是怎么做到的?

    很多人好奇平安E行销打卡到底是怎么破解的,为什么明明需要连接公司职场WiFi才可以参会,才可以刷脸打卡.为什么不用去公司,在家里,或者外面只要有4G或WiFi的地方都可以.今天我就来给大家解密.把原理 ...

  3. channelartlist|频道文档:

    http://help.dedecms.com/v53/archives/tag/global/channelartlist/ {/dede:channelartlist} 参数说明: typeid ...

  4. Mac 下 搭建 svn 服务器

    Mac自带了svn服务端和客户端,所以只需要简单配置一下就可以使用. 1.创建svn repository svnadmin create /Users/gaohf/svn/repository 2. ...

  5. Google免费GPU使用教程

    今天突然看到一篇推文,里面讲解了如何薅资本主义羊毛,即如何免费使用Google免费提供的GPU使用权. 可以免费使用的方式就是通过Google Colab,全名Colaboratory.我们可以用它来 ...

  6. Java数据持久层框架 MyBatis之API学习四(xml配置文件详解)

    摘录网址: http://blog.csdn.net/u010107350/article/details/51292500 对于MyBatis的学习而言,最好去MyBatis的官方文档:http:/ ...

  7. vim编辑操作

    vim    插入模式        a    光标后        A    行尾        o    光标所在行下一行        O    光标所在行上一行        i    光标前 ...

  8. 改变UITableView选中行高亮的颜色

    UIView *backView = [[UIView alloc] initWithFrame:self.contentView.frame]; backView.backgroundColor = ...

  9. php实现监控在线服务应用程序小栗子

    下面我就给大家举个栗子(例子) 某单位需要实现监控服务器状态,和监控服务器应用网站,还有需要监控服务器的中间件,数据库状态监控.听到这个任务是不是恨透头疼,这想起来是不是头疼.还好有系统可用,但是我现 ...

  10. Centos7 开放防火墙端口命令

    Centos 7 使用firewalld代替了原来的iptables,使用方法如下: >>>关闭防火墙 systemctl stop firewalld.service       ...