merge: 合并代码20240706
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/services"
|
||||
)
|
||||
|
||||
// 已禁用
|
||||
// 登录策略限制登录时间和访问ip范围
|
||||
func ArrowIPAddr(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
|
||||
// 读取配置信息 登录策略设置
|
||||
result, err := dborm.XormGetConfig("Security", "loginSecurity")
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
data := make(map[string]any)
|
||||
err = json.Unmarshal([]byte(result["value_json"].(string)), &data)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 开关
|
||||
switchStr := data["switch"].(string)
|
||||
if switchStr == "0" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ipRange := data["ipRange"].(string)
|
||||
logintimeRange := data["logintime_range"].(string)
|
||||
|
||||
// 检查ip
|
||||
ips := strings.Split(ipRange, "/")
|
||||
hasIP := false
|
||||
for _, ip := range ips {
|
||||
if ipAddr == ip {
|
||||
hasIP = true
|
||||
}
|
||||
}
|
||||
if !hasIP {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-IP限制: "+ipAddr)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查开放时间
|
||||
logintimeRangeArr := strings.Split(logintimeRange, " - ")
|
||||
|
||||
// 加载中国时区
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
// 获取当前时间
|
||||
currentTime := time.Now().In(loc)
|
||||
|
||||
// 获取当前日期
|
||||
currentDate := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location())
|
||||
ymd := currentDate.Format("2006-01-02")
|
||||
|
||||
// 定义开始时间和结束时间
|
||||
startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[0], loc)
|
||||
endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[1], loc)
|
||||
|
||||
// 判断当前时间是否在范围内
|
||||
if currentTime.After(startTime) && currentTime.Before(endTime) {
|
||||
next.ServeHTTP(w, r)
|
||||
} else {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-不在开放时间范围内")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"be.ems/lib/core/cache"
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/vo"
|
||||
"be.ems/lib/core/vo/result"
|
||||
"be.ems/lib/dborm"
|
||||
commonConstants "be.ems/src/framework/constants/common"
|
||||
tokenUtils "be.ems/src/framework/utils/token"
|
||||
)
|
||||
|
||||
// 已禁用由Gin部分接管
|
||||
// Authorize 用户身份授权认证校验
|
||||
//
|
||||
// 只需含有其中角色 "hasRoles": {"xxx"},
|
||||
//
|
||||
// 只需含有其中权限 "hasPerms": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中角色 "matchRoles": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中权限 "matchPerms": {"xxx"},
|
||||
func Authorize(options map[string][]string) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取请求头标识信息
|
||||
tokenStr := ctx.Authorization(r)
|
||||
// 获取请求头标识信息-旧头
|
||||
accessToken := r.Header.Get("AccessToken")
|
||||
if tokenStr == "" && accessToken != "" {
|
||||
// 验证令牌 == 这里直接查数据库session
|
||||
if !dborm.XormExistValidToken(accessToken, 0) {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
se, err := dborm.XormUpdateSessionShakeTime(accessToken)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
data, ok := cache.GetLocalTTL(se.AccountId)
|
||||
if data == nil || !ok {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization info error"))
|
||||
return
|
||||
}
|
||||
loginUser := data.(vo.LoginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求头标识信息
|
||||
if tokenStr == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization token error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证令牌
|
||||
claims, err := tokenUtils.Verify(tokenStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
loginUser := tokenUtils.LoginUser(claims)
|
||||
if loginUser.UserID == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查刷新有效期后存入上下文
|
||||
tokenUtils.RefreshIn(&loginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// verifyRolePermission 校验角色权限是否满足
|
||||
//
|
||||
// roles 角色字符数组
|
||||
//
|
||||
// perms 权限字符数组
|
||||
//
|
||||
// options 参数
|
||||
func verifyRolePermission(roles, perms []string, options map[string][]string) bool {
|
||||
// 直接放行 管理员角色或任意权限
|
||||
if contains(roles, "admin") || contains(perms, "*:*:*") {
|
||||
return true
|
||||
}
|
||||
opts := make([]bool, 4)
|
||||
|
||||
// 只需含有其中角色
|
||||
hasRole := false
|
||||
if arr, ok := options["hasRoles"]; ok && len(arr) > 0 {
|
||||
hasRole = some(roles, arr)
|
||||
opts[0] = true
|
||||
}
|
||||
|
||||
// 只需含有其中权限
|
||||
hasPerms := false
|
||||
if arr, ok := options["hasPerms"]; ok && len(arr) > 0 {
|
||||
hasPerms = some(perms, arr)
|
||||
opts[1] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中角色
|
||||
matchRoles := false
|
||||
if arr, ok := options["matchRoles"]; ok && len(arr) > 0 {
|
||||
matchRoles = every(roles, arr)
|
||||
opts[2] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中权限
|
||||
matchPerms := false
|
||||
if arr, ok := options["matchPerms"]; ok && len(arr) > 0 {
|
||||
matchPerms = every(perms, arr)
|
||||
opts[3] = true
|
||||
}
|
||||
|
||||
// 同时判断 含有其中
|
||||
if opts[0] && opts[1] {
|
||||
return hasRole || hasPerms
|
||||
}
|
||||
// 同时判断 匹配其中
|
||||
if opts[2] && opts[3] {
|
||||
return matchRoles && matchPerms
|
||||
}
|
||||
// 同时判断 含有其中且匹配其中
|
||||
if opts[0] && opts[3] {
|
||||
return hasRole && matchPerms
|
||||
}
|
||||
if opts[1] && opts[2] {
|
||||
return hasPerms && matchRoles
|
||||
}
|
||||
|
||||
return hasRole || hasPerms || matchRoles || matchPerms
|
||||
}
|
||||
|
||||
// contains 检查字符串数组中是否包含指定的字符串
|
||||
func contains(arr []string, target string) bool {
|
||||
for _, str := range arr {
|
||||
if str == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// some 检查字符串数组中含有其中一项
|
||||
func some(origin []string, target []string) bool {
|
||||
has := false
|
||||
for _, t := range target {
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
has = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if has {
|
||||
break
|
||||
}
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
// every 检查字符串数组中同时包含所有项
|
||||
func every(origin []string, target []string) bool {
|
||||
match := true
|
||||
for _, t := range target {
|
||||
found := false
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 已禁用由Gin部分接管
|
||||
// Cors 跨域
|
||||
func Cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 设置Vary头部
|
||||
w.Header().Set("Vary", "Origin")
|
||||
w.Header().Set("Keep-Alive", "timeout=5")
|
||||
|
||||
requestOrigin := r.Header.Get("Origin")
|
||||
if requestOrigin == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
// OPTIONS
|
||||
if r.Method == "OPTIONS" {
|
||||
requestMethod := r.Header.Get("Access-Control-Request-Method")
|
||||
if requestMethod == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 响应最大时间值
|
||||
w.Header().Set("Access-Control-Max-Age", "31536000")
|
||||
|
||||
// 允许方法
|
||||
allowMethods := []string{
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowMethods, ","))
|
||||
|
||||
// 允许请求头
|
||||
allowHeaders := []string{
|
||||
"Accesstoken",
|
||||
"Content-Type",
|
||||
"operationtype",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Headers", strings.Join(allowHeaders, ","))
|
||||
|
||||
w.WriteHeader(204)
|
||||
return
|
||||
}
|
||||
|
||||
// 暴露请求头
|
||||
exposeHeaders := []string{"X-RepeatSubmit-Rest", "AccessToken"}
|
||||
w.Header().Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/datasource"
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/utils/date"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/utils/date"
|
||||
)
|
||||
|
||||
// LogMML mml操作日志搜集
|
||||
@@ -36,7 +36,7 @@ func LogMML(next http.Handler) http.Handler {
|
||||
// 收尾存入数据库的参数
|
||||
mmlCmd := bodyArgs["mml"].([]any)[0]
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
neType := ctx.Param(r, "elementTypeValue")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/utils/parse"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/src/framework/constants/common"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/utils/ip2region"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/system/model"
|
||||
"be.ems/src/modules/system/service"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user