buid-in dashboard security update

This commit is contained in:
Max 2022-02-17 17:05:25 +08:00
parent 03f220c9c1
commit 5ce9df8495
15 changed files with 191 additions and 184 deletions

File diff suppressed because one or more lines are too long

3
go.mod
View file

@ -10,7 +10,6 @@ require (
github.com/buraksezer/consistent v0.9.0 // indirect
github.com/buraksezer/olric v0.4.2
github.com/caarlos0/env/v6 v6.9.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/elazarl/go-bindata-assetfs v1.0.1
github.com/fatih/color v1.13.0
github.com/fsnotify/fsnotify v1.5.1
@ -56,4 +55,4 @@ replace github.com/yaoapp/xun => ../xun // gou local
replace github.com/yaoapp/gou => ../gou // gou local
replace rogchap.com/v8go => ../v8go
replace rogchap.com/v8go => ../v8go

4
go.sum
View file

@ -101,8 +101,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -884,8 +882,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rogchap.com/v8go v0.7.0 h1:kgjbiO4zE5itA962ze6Hqmbs4HgZbGzmueCXsZtremg=
rogchap.com/v8go v0.7.0/go.mod h1:MxgP3pL2MW4dpme/72QRs8sgNMmM0pRc8DPhcuLWPAs=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View file

@ -9,6 +9,7 @@ import (
"github.com/yaoapp/gou/session"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
)
@ -33,7 +34,8 @@ func JwtValidate(tokenString string) *JwtClaims {
})
if err != nil {
exception.New("令牌无效", 403).Ctx(err.Error()).Throw()
log.Error("JWT ParseWithClaims Error: %s", err)
exception.New("Invalid token", 403).Ctx(err.Error()).Throw()
return nil
}
@ -41,7 +43,7 @@ func JwtValidate(tokenString string) *JwtClaims {
return claims
}
exception.New("令牌无效", 403).Ctx(token.Claims).Throw()
exception.New("Invalid token", 403).Ctx(token.Claims).Throw()
return nil
}

View file

@ -1,13 +1,9 @@
package service
import (
"fmt"
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/helper"
)
@ -20,35 +16,16 @@ var Guards = map[string]gin.HandlerFunc{
// JWT 鉴权
func bearerJWT(c *gin.Context) {
tokenString := c.Request.Header.Get("Authorization")
tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer "))
if tokenString == "" {
c.JSON(403, gin.H{"code": 403, "message": "无权访问该页面"})
c.Abort()
return
}
tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer "))
log.Debug("JWT: %s Secret: %s", tokenString, config.Conf.JWTSecret)
token, err := jwt.ParseWithClaims(tokenString, &helper.JwtClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(config.Conf.JWTSecret), nil
})
if err != nil {
log.Error("JWT ParseWithClaims Error: %s", err)
c.JSON(403, gin.H{"code": 403, "message": fmt.Sprintf("登录已过期或令牌失效(%s)", err)})
c.Abort()
return
}
if claims, ok := token.Claims.(*helper.JwtClaims); ok && token.Valid {
c.Set("__sid", claims.SID)
c.Next()
return
}
// fmt.Println("bearer-JWT", token.Claims.Valid())
c.JSON(403, gin.H{"code": 403, "message": "无权访问该页面"})
c.Abort()
return
claims := helper.JwtValidate(tokenString)
c.Set("__sid", claims.SID)
c.Next()
}
// crossDomain 跨域访问

View file

@ -15,7 +15,7 @@ import (
"github.com/yaoapp/kun/utils"
)
// IsAllow 鉴权处理程序
// IsAllow 鉴权处理程序 (废弃)
func (api API) IsAllow(v interface{}) bool {
c, ok := v.(*gin.Context)
if !ok {

View file

@ -21,8 +21,8 @@ func apiSearchDefault(model *gou.Model, withs map[string]gou.With) share.API {
}
return share.API{
Name: "search",
Guard: "bearer-jwt",
Name: "search",
// Guard: "bearer-jwt",
Process: fmt.Sprintf("models.%s.Paginate", model.Name),
Default: []interface{}{query, 1, 20},
}
@ -37,8 +37,8 @@ func apiFindDefault(model *gou.Model, withs map[string]gou.With) share.API {
}
return share.API{
Name: "find",
Guard: "bearer-jwt",
Name: "find",
// Guard: "bearer-jwt",
Process: fmt.Sprintf("models.%s.Find", model.Name),
Default: []interface{}{nil, query},
}
@ -47,8 +47,8 @@ func apiFindDefault(model *gou.Model, withs map[string]gou.With) share.API {
// apiDefault 接口默认值
func apiDefault(model *gou.Model, name string, process string) share.API {
return share.API{
Name: name,
Guard: "bearer-jwt",
Name: name,
// Guard: "bearer-jwt",
Process: fmt.Sprintf("models.%s.%s", model.Name, process),
}
}
@ -62,8 +62,8 @@ func apiDefaultWhere(model *gou.Model, withs map[string]gou.With, name string, p
}
return share.API{
Name: name,
Guard: "bearer-jwt",
Name: name,
// Guard: "bearer-jwt",
Process: fmt.Sprintf("models.%s.%s", model.Name, process),
Default: []interface{}{query},
}
@ -72,8 +72,8 @@ func apiDefaultWhere(model *gou.Model, withs map[string]gou.With, name string, p
// apiDefaultSetting 数据表格配置默认值
func apiDefaultSetting() share.API {
return share.API{
Name: "setting",
Guard: "bearer-jwt",
Name: "setting",
// Guard: "bearer-jwt",
Process: fmt.Sprintf("xiang.table.setting"),
}
}

View file

@ -35,9 +35,11 @@ func ProcessSearch(process *gou.Process) interface{} {
table := Select(name)
api := table.APIs["search"].ValidateLoop("xiang.table.search")
if process.NumOfArgsIs(5) && api.IsAllow(process.Args[4]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// if process.NumOfArgsIs(5) && api.IsAllow(process.Args[4]) {
// return nil
// }
// Before Hook
process.Args = table.Before(table.Hooks.BeforeSearch, process.Args, process.Sid)
@ -64,9 +66,7 @@ func ProcessFind(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["find"].ValidateLoop("xiang.table.find")
if process.NumOfArgsIs(3) && api.IsAllow(process.Args[2]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// Before Hook
process.Args = table.Before(table.Hooks.BeforeFind, process.Args, process.Sid)
@ -92,9 +92,7 @@ func ProcessSave(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["save"].ValidateLoop("xiang.table.save")
// if process.NumOfArgsIs(3) && api.IsAllow(process.Args[2]) {
// return nil
// }
table.APIGuard(api.Guard, process.Sid, process.Global)
// Before Hook
process.Args = table.Before(table.Hooks.BeforeSave, process.Args, process.Sid)
@ -116,9 +114,7 @@ func ProcessDelete(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["delete"].ValidateLoop("xiang.table.delete")
if process.NumOfArgsIs(3) && api.IsAllow(process.Args[2]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
id := process.Args[1]
return gou.NewProcess(api.Process, id).Run()
@ -132,9 +128,7 @@ func ProcessDeleteWhere(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["delete-where"].ValidateLoop("xiang.table.DeleteWhere")
if process.NumOfArgsIs(3) && api.IsAllow(process.Args[2]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// 批量删除
param := api.MergeDefaultQueryParam(process.ArgsQueryParams(1), 0, process.Sid)
@ -153,9 +147,7 @@ func ProcessDeleteIn(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["delete-in"].ValidateLoop("xiang.table.DeleteIn")
if process.NumOfArgsIs(4) && api.IsAllow(process.Args[3]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// 批量删除
ids := strings.Split(process.ArgsString(1), ",")
@ -177,9 +169,7 @@ func ProcessUpdateWhere(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["update-where"].ValidateLoop("xiang.table.UpdateWhere")
if process.NumOfArgsIs(4) && api.IsAllow(process.Args[3]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// 批量更新
param := api.MergeDefaultQueryParam(process.ArgsQueryParams(1), 0, process.Sid)
@ -197,9 +187,7 @@ func ProcessUpdateIn(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["update-in"].ValidateLoop("xiang.table.UpdateIn")
if process.NumOfArgsIs(5) && api.IsAllow(process.Args[4]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// 批量删除
ids := strings.Split(process.ArgsString(1), ",")
@ -219,9 +207,7 @@ func ProcessInsert(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["insert"].ValidateLoop("xiang.table.Insert")
if process.NumOfArgsIs(4) && api.IsAllow(process.Args[3]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
return gou.NewProcess(api.Process, process.Args[1:]...).Run()
}
@ -233,9 +219,7 @@ func ProcessSetting(process *gou.Process) interface{} {
field := process.ArgsString(1)
table := Select(name)
api := table.APIs["setting"]
if process.NumOfArgsIs(2) && api.IsAllow(process.Args[1]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
fields := strings.Split(field, ",")
if api.ProcessIs("xiang.table.Setting") {
@ -280,9 +264,7 @@ func ProcessQuickSave(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["quicksave"].ValidateLoop("xiang.table.quicksave")
if process.NumOfArgsIs(3) && api.IsAllow(process.Args[2]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
args := []interface{}{}
payload := process.ArgsMap(1)
@ -312,9 +294,7 @@ func ProcessSelect(process *gou.Process) interface{} {
name := process.ArgsString(0)
table := Select(name)
api := table.APIs["select"].ValidateLoop("xiang.table.select")
if process.NumOfArgsIs(5) && api.IsAllow(process.Args[4]) {
return nil
}
table.APIGuard(api.Guard, process.Sid, process.Global)
// Before Hook
process.Args = table.Before(table.Hooks.BeforeSelect, process.Args, process.Sid)

View file

@ -125,9 +125,10 @@ func (table *Table) loadAPIs() {
api.Process = table.APIs[name].Process
}
if table.APIs[name].Guard != "" {
api.Guard = table.APIs[name].Guard
}
// if table.APIs[name].Guard != "" {
// api.Guard = table.APIs[name].Guard
// }
if table.APIs[name].Default != nil {
// fmt.Printf("\n%s.APIs[%s].Default: entry\n", table.Table, name)
if len(table.APIs[name].Default) == len(api.Default) {
@ -208,6 +209,22 @@ func (table *Table) After(process string, data interface{}, args []interface{},
return response
}
// APIGuard API鉴权
func (table *Table) APIGuard(guard string, sid string, global map[string]interface{}, args ...interface{}) {
if guard == "" {
guard = table.Guard
}
if guard == "-" || guard == "" {
return
}
log.With(log.F{"args": args}).Debug(guard)
gou.NewProcess(guard, args...).
WithSID(sid).
WithGlobal(global).
Run()
}
// loadFilters 加载查询过滤器
func (table *Table) loadFilters() {
if table.Bind.Model == "" {

View file

@ -9,6 +9,7 @@ import (
type Table struct {
Table string `json:"-"`
Source string `json:"-"`
Guard string `json:"guard,omitempty"`
Name string `json:"name"`
Version string `json:"version"`
Title string `json:"title,omitempty"`

View file

@ -72,6 +72,7 @@ func Auth(field string, value string, password string) maps.Map {
})
session.Global().Expire(time.Duration(token.ExpiresAt)*time.Second).ID(sid).Set("user_id", id)
session.Global().ID(sid).Set("user", row)
session.Global().ID(sid).Set("issuer", "xiang")
// 读取菜单
menus := gou.NewProcess("flows.xiang.menu").Run()

View file

@ -0,0 +1,25 @@
{
"label": "后台用户鉴权",
"version": "1.0.0",
"description": "后台用户鉴权",
"nodes": [
{
"name": "签发人",
"process": "session.Get",
"args": ["issuer"]
},
{
"name": "鉴权",
"process": "xiang.flow.IF",
"args": [
{
"when": [{ "用户身份": "{{$res.签发人}}", "!=": "xiang" }],
"name": "更新用户资料",
"process": "xiang.flow.Throw",
"args": ["token 签发人不合法", 403]
}
]
}
],
"output": "success"
}

View file

@ -1,16 +0,0 @@
{
"label": "用户资料",
"version": "1.0.0",
"description": "菜单列表",
"nodes": [
{
"name": "user",
"process": "models.xiang.user.Find",
"args": [
"{{$in.0}}",
{ "select": ["id", "name", "type", "mobile", "email", "status"] }
]
}
],
"output": "{{$res.user}}"
}

View file

@ -5,6 +5,7 @@
"bind": {
"model": "xiang.menu"
},
"guard": "flows.xiang.admin.guard",
"apis": {
"search": {
"process": "models.xiang.menu.Paginate",

View file

@ -2,6 +2,7 @@
"name": "用户",
"version": "1.0.0",
"decription": "象传用户",
"guard": "flows.xiang.admin.guard",
"bind": {
"model": "xiang.user"
},