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

掘金: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. Android studio启动后卡在refreshing gradle project(包解决)

    这个问题几乎每个刚使用Android studio的同学都会碰到过,网上有各式各样的方法,有的说使用本地gradle,我试过多次,每次启动android studio时还是会检查更新,所以根本上解决的 ...

  2. day2 作业

    1.判断下列逻辑语句的True,False. 1),1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6     ...

  3. Tomcat服务器的下载及安装

    Tomcat服务器的下载及安装 1)到apache官网.www.apache.org     http://jakarta.apache.org(产品的主页) 2) 安装版:window (exe.m ...

  4. 学习JVM-GC收集器

    1. 前言 在上一篇文章中,介绍了JVM中垃圾回收的原理和算法.介绍了通过引用计数和对象可达性分析的算法来筛选出已经没有使用的对象,然后介绍了垃圾收集器中使用的三种收集算法:标记-清除.标记-整理.标 ...

  5. CSS容器属性

    最近一直想美化博客的文字效果和增加文章末尾的转发提示,所以这两天抽空研究了一下CSS,前两篇可以翻我的博客,今天写的这篇是介绍增加文章末尾的转发提示,效果如文章末尾所示,好了,CSS很简单,我就不介绍 ...

  6. IOS学习笔记25—HTTP操作之ASIHTTPRequest(一)

    ASIHTTPRequest是一个第三方开源项目,在现在的IOS应用中多使用到这个开源类库来提供网络操作,相比于SDK提供的网络操作类库,ASIHTTPRequest使用上更加方便.效率更高,同时功能 ...

  7. Java并发编程:Thread类的使用(转载)

    一:线程的状态: 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程 ...

  8. Mybatis延迟加载和查询缓存

    摘录自:http://www.linuxidc.com/Linux/2016-07/133593.htm 阅读目录 一.延迟加载 二.查询缓存 一.延迟加载 resultMap可以实现高级映射(使用a ...

  9. 微信跳一跳的mini辅助设计

    前一段考试没时间写东西,就迟到补发一波,继电器触发触屏,arduino处理数据就行了,B站很多人做,我也来一个,个人测试数据增益为2.1左右,即  延时=距离X2.1x10 void setup() ...

  10. arduino笔记

    接下来,初来博客,准备自己也写一系列的arduino的学习经验. http://zhongbest.com/2017/05/23/arduino%e4%b8%ad%e7%9a%84%e4%b8%ad% ...