作者 yangfu

增加过滤器 验证 sign access_toke uuid

@@ -5,6 +5,8 @@ runmode = dev @@ -5,6 +5,8 @@ runmode = dev
5 #没设置的话 this.Ctx.Input.RequestBody 没有值 5 #没设置的话 this.Ctx.Input.RequestBody 没有值
6 copyrequestbody = true 6 copyrequestbody = true
7 7
  8 +#enablexsrf = true
  9 +
8 #开启应用内文档开关 10 #开启应用内文档开关
9 EnableDocs = true 11 EnableDocs = true
10 12
1 package controllers 1 package controllers
2 2
3 import ( 3 import (
  4 + "crypto/sha256"
  5 + "encoding/hex"
  6 + "fmt"
  7 + "github.com/astaxie/beego"
  8 + "github.com/astaxie/beego/context"
4 "github.com/astaxie/beego/validation" 9 "github.com/astaxie/beego/validation"
  10 + "gitlab.fjmaimaimai.com/mmm-go/ability/protocol"
  11 + "gitlab.fjmaimaimai.com/mmm-go/ability/services/auth"
5 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common" 12 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
6 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log" 13 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
7 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/mybeego" 14 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/mybeego"
  15 + "strconv"
  16 +
  17 + //"strconv"
  18 + "strings"
8 ) 19 )
9 20
10 type BaseController struct { 21 type BaseController struct {
11 mybeego.BaseController 22 mybeego.BaseController
12 } 23 }
13 - 24 +var DefaultController *BaseController = &BaseController{}
14 //Valid valid struct 25 //Valid valid struct
15 func (this *BaseController)Valid(obj interface{})(result bool ,msg *mybeego.Message){ 26 func (this *BaseController)Valid(obj interface{})(result bool ,msg *mybeego.Message){
16 /*校验*/ 27 /*校验*/
@@ -48,3 +59,104 @@ func (this *BaseController)GenMessage(rsp interface{},err error)*mybeego.Message @@ -48,3 +59,104 @@ func (this *BaseController)GenMessage(rsp interface{},err error)*mybeego.Message
48 msg = mybeego.NewMessage(1) 59 msg = mybeego.NewMessage(1)
49 return msg 60 return msg
50 } 61 }
  62 +
  63 +func GetRequestHeader(ctx *context.Context)*protocol.RequestHeader{
  64 + h :=&protocol.RequestHeader{}
  65 + h.AccessToken = ctx.Input.Header("x-mmm-accesstoken")
  66 + h.AppProject = ctx.Input.Header("x-mmm-appproject")
  67 + h.DeviceType = ctx.Input.Header("x-mmm-devicetype")
  68 + h.Sign = ctx.Input.Header("x-mmm-sign")
  69 + h.Uuid = ctx.Input.Header("x-mmm-uuid")
  70 + h.TimeStamp = ctx.Input.Header("x-mmm-timestamp")
  71 + h.Uid,_=strconv.ParseInt(ctx.Input.Header("uid"),10,64)//需要uid写入到header里面
  72 + return h
  73 +}
  74 +
  75 +func FilterComm(ctx *context.Context){
  76 + if strings.HasSuffix(ctx.Request.RequestURI,"login"){
  77 + return
  78 + }
  79 + if beego.BConfig.RunMode!="prod"{
  80 + return
  81 + }
  82 + //1.检查签名
  83 + if !CheckSign(ctx){
  84 + return
  85 + }
  86 + //2.检查token是否有效
  87 + if !CheckToken(ctx){
  88 + return
  89 + }
  90 + //3.查重uuid
  91 + if !CheckUuid(ctx){
  92 + return
  93 + }
  94 + return
  95 +}
  96 +//检查签名
  97 +func CheckSign(ctx *context.Context)(result bool){
  98 + var(
  99 + h *protocol.RequestHeader
  100 + sign string
  101 + signHex string
  102 + )
  103 + result = true
  104 + h =GetRequestHeader(ctx)
  105 + //1.检查签名
  106 + sign =fmt.Sprintf("v!(MmM%v%v%vMmM)i^",h.TimeStamp,h.Uuid,h.AccessToken)
  107 + sha256:=sha256.New()
  108 + sha256.Write([]byte(sign))
  109 + signHex = hex.EncodeToString(sha256.Sum(nil))
  110 + if strings.Compare(signHex,h.Sign)!=0{
  111 + msg :=mybeego.NewMessage(113)
  112 + log.Error(fmt.Sprintf("%v req:%v resp:%v %v",ctx.Request.RequestURI,common.AssertJson(h),common.AssertJson(msg),signHex))
  113 + ctx.Output.JSON(msg, false, false)
  114 + result =false
  115 + return
  116 + }
  117 + return
  118 +}
  119 +//检查access_token
  120 +func CheckToken(ctx *context.Context)(result bool){
  121 + var (
  122 + msg *mybeego.Message
  123 + )
  124 + result = true
  125 + defer func(){
  126 + if msg!=nil{
  127 + result =false
  128 + ctx.Output.JSON(msg,false,false)
  129 + }
  130 + }()
  131 + token := ctx.Input.Header("x-mmm-accesstoken")
  132 + if rsp,err:=auth.CheckToken(&protocol.CheckTokenRequest{Token:token});(err!=nil || rsp.UserInfo==nil){
  133 + msg = DefaultController.GenMessage(rsp,err)
  134 + log.Error(fmt.Sprintf("%v req:%v resp:%v",ctx.Request.RequestURI,token,common.AssertJson(msg)))
  135 + return
  136 + }else{
  137 + if rsp.UserInfo!=nil{
  138 + //设置附加数据
  139 + ctx.Request.Header.Add("uid",fmt.Sprintf("%v",rsp.UserInfo.Uuid))
  140 + }
  141 + }
  142 + return
  143 +}
  144 +//检查Uuid
  145 +func CheckUuid(ctx *context.Context)(result bool){
  146 + var (
  147 + msg *mybeego.Message
  148 + )
  149 + result = true
  150 + defer func(){
  151 + if msg!=nil{
  152 + result =false
  153 + ctx.Output.JSON(msg,false,false)
  154 + }
  155 + }()
  156 + uuid := ctx.Input.Header("x-mmm-uuid")
  157 + msg = DefaultController.GenMessage(auth.CheckUuid(&protocol.CheckUuidRequest{Uuid:uuid}))
  158 + if msg!=nil{
  159 + log.Error(fmt.Sprintf("%v req:%v resp:%v",ctx.Request.RequestURI,uuid,common.AssertJson(msg)))
  160 + }
  161 + return
  162 +}
@@ -3,6 +3,7 @@ package main @@ -3,6 +3,7 @@ package main
3 import ( 3 import (
4 "github.com/astaxie/beego" 4 "github.com/astaxie/beego"
5 _ "github.com/go-sql-driver/mysql" 5 _ "github.com/go-sql-driver/mysql"
  6 + "gitlab.fjmaimaimai.com/mmm-go/ability/controllers"
6 "gitlab.fjmaimaimai.com/mmm-go/ability/protocol" 7 "gitlab.fjmaimaimai.com/mmm-go/ability/protocol"
7 _ "gitlab.fjmaimaimai.com/mmm-go/ability/routers" 8 _ "gitlab.fjmaimaimai.com/mmm-go/ability/routers"
8 "gitlab.fjmaimaimai.com/mmm-go/gocomm/config" 9 "gitlab.fjmaimaimai.com/mmm-go/gocomm/config"
@@ -32,6 +33,7 @@ func main() { @@ -32,6 +33,7 @@ func main() {
32 defer func(){ 33 defer func(){
33 log.Info("app on stop!") 34 log.Info("app on stop!")
34 }() 35 }()
  36 + beego.InsertFilter("/*",beego.BeforeRouter,controllers.FilterComm)
35 protocol.InitMessageCode() 37 protocol.InitMessageCode()
36 log.Info("app on start!") 38 log.Info("app on start!")
37 log.Info("Beego Run Mode:",beego.BConfig.RunMode) 39 log.Info("Beego Run Mode:",beego.BConfig.RunMode)
@@ -10,7 +10,7 @@ import ( @@ -10,7 +10,7 @@ import (
10 ) 10 )
11 11
12 type LogUuid struct { 12 type LogUuid struct {
13 - Id int `orm:"column(id);auto" description:"主键ID"` 13 + Id int64 `orm:"column(id);auto" description:"主键ID"`
14 Uuid string `orm:"column(uuid);size(128)"` 14 Uuid string `orm:"column(uuid);size(128)"`
15 } 15 }
16 16
@@ -32,7 +32,7 @@ func AddLogUuid(m *LogUuid) (id int64, err error) { @@ -32,7 +32,7 @@ func AddLogUuid(m *LogUuid) (id int64, err error) {
32 32
33 // GetLogUuidById retrieves LogUuid by Id. Returns error if 33 // GetLogUuidById retrieves LogUuid by Id. Returns error if
34 // Id doesn't exist 34 // Id doesn't exist
35 -func GetLogUuidById(id int) (v *LogUuid, err error) { 35 +func GetLogUuidById(id int64) (v *LogUuid, err error) {
36 o := orm.NewOrm() 36 o := orm.NewOrm()
37 v = &LogUuid{Id: id} 37 v = &LogUuid{Id: id}
38 if err = o.Read(v); err == nil { 38 if err = o.Read(v); err == nil {
@@ -136,7 +136,7 @@ func UpdateLogUuidById(m *LogUuid) (err error) { @@ -136,7 +136,7 @@ func UpdateLogUuidById(m *LogUuid) (err error) {
136 136
137 // DeleteLogUuid deletes LogUuid by Id and returns error if 137 // DeleteLogUuid deletes LogUuid by Id and returns error if
138 // the record to be deleted doesn't exist 138 // the record to be deleted doesn't exist
139 -func DeleteLogUuid(id int) (err error) { 139 +func DeleteLogUuid(id int64) (err error) {
140 o := orm.NewOrm() 140 o := orm.NewOrm()
141 v := LogUuid{Id: id} 141 v := LogUuid{Id: id}
142 // ascertain id exists in the database 142 // ascertain id exists in the database
@@ -148,3 +148,12 @@ func DeleteLogUuid(id int) (err error) { @@ -148,3 +148,12 @@ func DeleteLogUuid(id int) (err error) {
148 } 148 }
149 return 149 return
150 } 150 }
  151 +
  152 +func GetLogUuidByUuid(uuid string)(v *LogUuid, err error) {
  153 + o := orm.NewOrm()
  154 + sql :="select * from log_uuid where uuid=?"
  155 + if err = o.Raw(sql,uuid).QueryRow(&v); err == nil {
  156 + return v, nil
  157 + }
  158 + return nil, err
  159 +}
@@ -208,3 +208,12 @@ func GetUserInfoByClientId(clintId string)(v *UserInfo, err error) { @@ -208,3 +208,12 @@ func GetUserInfoByClientId(clintId string)(v *UserInfo, err error) {
208 return nil, err 208 return nil, err
209 } 209 }
210 210
  211 +func GetUserInfoByToken(token string)(v *UserInfo, err error) {
  212 + o := orm.NewOrm()
  213 + sql :="select * from user_info where access_token=? and access_exp >= Now() and enabled = 1"
  214 + if err = o.Raw(sql,token).QueryRow(&v); err == nil {
  215 + return v, nil
  216 + }
  217 + return nil, err
  218 +}
  219 +
1 package protocol 1 package protocol
2 2
  3 +import "gitlab.fjmaimaimai.com/mmm-go/ability/models"
  4 +
3 const ( 5 const (
4 LoginPassPord ="signInPassword" 6 LoginPassPord ="signInPassword"
5 LoginSmdcode ="signInCaptcha" 7 LoginSmdcode ="signInCaptcha"
6 ) 8 )
7 9
  10 +type RequestHeader struct {
  11 + TimeStamp string
  12 + Uuid string
  13 + Sign string
  14 + DeviceType string
  15 + AppProject string
  16 + AccessToken string
  17 + Uid int64
  18 +}
  19 +
8 /*Login */ 20 /*Login */
9 type LoginRequest struct { 21 type LoginRequest struct {
10 Phone string `json:"phone" valid:"Required;Mobile"` 22 Phone string `json:"phone" valid:"Required;Mobile"`
@@ -63,3 +75,20 @@ type Access struct { @@ -63,3 +75,20 @@ type Access struct {
63 RefreshToken string 75 RefreshToken string
64 } 76 }
65 77
  78 +/*CheckToken */
  79 +type CheckTokenRequest struct {
  80 + Token string
  81 +}
  82 +type CheckTokenResponse struct {
  83 + IsValid bool //true:过期 false:没有过期
  84 + UserInfo *models.UserInfo
  85 +}
  86 +
  87 +
  88 +/*CheckUuid */
  89 +type CheckUuidRequest struct {
  90 + Uuid string
  91 +}
  92 +type CheckUuidResponse struct {
  93 +}
  94 +
@@ -102,3 +102,39 @@ func RefreshToken(request *protocol.RefreshTokenRequest)(rsp *protocol.RefreshTo @@ -102,3 +102,39 @@ func RefreshToken(request *protocol.RefreshTokenRequest)(rsp *protocol.RefreshTo
102 func refreshToken(uid int64,loginType string)(rsp *protocol.Access,err error){ 102 func refreshToken(uid int64,loginType string)(rsp *protocol.Access,err error){
103 return nil,nil 103 return nil,nil
104 } 104 }
  105 +
  106 +func CheckToken(request *protocol.CheckTokenRequest)(rsp *protocol.CheckTokenResponse,err error){
  107 + var (
  108 + userInfo *models.UserInfo
  109 + )
  110 + if len(request.Token)==0{
  111 + err = common.NewErrorWithMsg(4141,"token not empty")
  112 + return
  113 + }
  114 + userInfo,err =models.GetUserInfoByToken(request.Token)
  115 + if err!=nil{
  116 + err =common.NewError(4141,err)
  117 + return
  118 + }
  119 + rsp =&protocol.CheckTokenResponse{
  120 + UserInfo:userInfo,
  121 + IsValid:true,
  122 + }
  123 + return
  124 +}
  125 +
  126 +func CheckUuid(request *protocol.CheckUuidRequest)(rsp *protocol.CheckUuidResponse,err error){
  127 + var (
  128 + logUuid *models.LogUuid
  129 + )
  130 + if len(request.Uuid)==0{
  131 + err = common.NewErrorWithMsg(4142,"uuid not empty")
  132 + }
  133 + logUuid,err=models.GetLogUuidByUuid(request.Uuid)
  134 + if err==nil && logUuid!=nil{
  135 + err = common.NewErrorWithMsg(4142,"uuid not empty")
  136 + }
  137 + models.AddLogUuid(&models.LogUuid{Uuid:request.Uuid})
  138 + rsp =&protocol.CheckUuidResponse{}
  139 + return
  140 +}