- Added Oauth2LogLoginService for managing user authorization logs. - Implemented methods for inserting logs, cleaning logs, and exporting log data. - Created a new file for Oauth2 login log service. refactor: Remove unused open_api module - Deleted the open_api.go file as it was not utilized in the project. fix: Update error codes in SysProfileController - Changed error codes for binding errors and user authentication errors to more descriptive values. fix: Update cache handling in SysConfig and SysDictType services - Modified Redis set operations to include expiration time for cached values. refactor: Update middleware authorization checks - Replaced PreAuthorize middleware with AuthorizeUser across multiple routes in system and tool modules for consistency. chore: Clean up trace and ws modules - Updated middleware authorization in trace and ws modules to use AuthorizeUser.
220 lines
4.8 KiB
Go
220 lines
4.8 KiB
Go
package middleware
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"be.ems/src/framework/config"
|
|
"be.ems/src/framework/constants"
|
|
"be.ems/src/framework/reqctx"
|
|
"be.ems/src/framework/resp"
|
|
"be.ems/src/framework/token"
|
|
"be.ems/src/framework/utils/parse"
|
|
)
|
|
|
|
/**无Token可访问白名单 */
|
|
var URL_WHITE_LIST = []string{
|
|
"/performanceManagement",
|
|
"/faultManagement",
|
|
"/systemState",
|
|
"/omcNeConfig",
|
|
"/cdrEvent",
|
|
"/ueEvent",
|
|
"/objectType/nbState",
|
|
"/upload-ue",
|
|
"/oauth/token",
|
|
}
|
|
|
|
// AuthorizeUser 用户身份授权认证校验
|
|
//
|
|
// 只需含有其中角色 "hasRoles": {"xxx"},
|
|
//
|
|
// 只需含有其中权限 "hasPerms": {"xxx"},
|
|
//
|
|
// 同时匹配其中角色 "matchRoles": {"xxx"},
|
|
//
|
|
// 同时匹配其中权限 "matchPerms": {"xxx"},
|
|
func AuthorizeUser(options map[string][]string) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// 登录认证,默认打开
|
|
enable := parse.Boolean(config.Get("serverLoginAuth"))
|
|
if !enable {
|
|
loginUser, _ := reqctx.LoginUser(c)
|
|
loginUser.UserId = 2
|
|
loginUser.User.UserId = 2
|
|
loginUser.User.UserName = "admin"
|
|
loginUser.User.NickName = "admin"
|
|
c.Set(constants.CTX_LOGIN_USER, loginUser)
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
// 判断白名单
|
|
isWhite := false
|
|
requestURI := c.Request.RequestURI
|
|
for _, w := range URL_WHITE_LIST {
|
|
if strings.Contains(requestURI, w) {
|
|
isWhite = true
|
|
break
|
|
}
|
|
}
|
|
if isWhite {
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
// 获取请求头标识信息
|
|
tokenStr := reqctx.Authorization(c)
|
|
if tokenStr == "" {
|
|
c.JSON(401, resp.CodeMsg(401003, "authorization token is empty"))
|
|
c.Abort() // 停止执行后续的处理函数
|
|
return
|
|
}
|
|
|
|
// 验证令牌
|
|
claims, err := token.UserTokenVerify(tokenStr, "access")
|
|
if err != nil {
|
|
c.JSON(401, resp.CodeMsg(401001, err.Error()))
|
|
c.Abort() // 停止执行后续的处理函数
|
|
return
|
|
}
|
|
|
|
// 获取缓存的用户信息
|
|
info := token.UserInfoGet(claims)
|
|
if info.UserId <= 0 {
|
|
c.JSON(401, resp.CodeMsg(401002, "invalid login user information"))
|
|
c.Abort() // 停止执行后续的处理函数
|
|
return
|
|
}
|
|
c.Set(constants.CTX_LOGIN_USER, info)
|
|
|
|
// 登录用户角色权限校验
|
|
if options != nil {
|
|
var roles []string
|
|
for _, item := range info.User.Roles {
|
|
roles = append(roles, item.RoleKey)
|
|
}
|
|
perms := info.Permissions
|
|
verifyOk := verifyRolePermission(roles, perms, options)
|
|
if !verifyOk {
|
|
msg := fmt.Sprintf("unauthorized access %s %s", c.Request.Method, c.Request.RequestURI)
|
|
c.JSON(403, resp.CodeMsg(403001, msg))
|
|
c.Abort() // 停止执行后续的处理函数
|
|
return
|
|
}
|
|
}
|
|
|
|
// 调用下一个处理程序
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// verifyRolePermission 校验角色权限是否满足
|
|
//
|
|
// roles 角色字符数组
|
|
//
|
|
// perms 权限字符数组
|
|
//
|
|
// options 参数
|
|
func verifyRolePermission(roles, perms []string, options map[string][]string) bool {
|
|
// 直接放行 系统管理员角色或任意权限
|
|
if contains(roles, constants.SYS_ROLE_SYSTEM_KEY) || contains(perms, constants.SYS_PERMISSION_SYSTEM) {
|
|
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
|
|
}
|