buid-in dashboard security update
This commit is contained in:
parent
03f220c9c1
commit
5ce9df8495
15 changed files with 191 additions and 184 deletions
189
data/bindata.go
189
data/bindata.go
File diff suppressed because one or more lines are too long
3
go.mod
3
go.mod
|
|
@ -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
4
go.sum
|
|
@ -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=
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 跨域访问
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
20
table/api.go
20
table/api.go
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 == "" {
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
25
yao/flows/admin/guard.flow.json
Normal file
25
yao/flows/admin/guard.flow.json
Normal 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"
|
||||
}
|
||||
|
|
@ -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}}"
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
"bind": {
|
||||
"model": "xiang.menu"
|
||||
},
|
||||
"guard": "flows.xiang.admin.guard",
|
||||
"apis": {
|
||||
"search": {
|
||||
"process": "models.xiang.menu.Paginate",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"name": "用户",
|
||||
"version": "1.0.0",
|
||||
"decription": "象传用户",
|
||||
"guard": "flows.xiang.admin.guard",
|
||||
"bind": {
|
||||
"model": "xiang.user"
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue