mirror of https://gitee.com/godoos/godoos.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
7.2 KiB
302 lines
7.2 KiB
package middleware
|
|
|
|
import (
|
|
"godocms/common"
|
|
"godocms/libs"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func JwtVerify() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
url := c.Request.URL.Path
|
|
// 检查 URL 是否以 /static/ 开头,如果是则跳过记录
|
|
if strings.HasPrefix(url, "/static/") || strings.HasPrefix(url, "/upload/") || strings.HasPrefix(url, "/views/") || strings.HasPrefix(url, "/os/") {
|
|
c.Next() // 继续后续处理
|
|
return
|
|
}
|
|
// 根据动态路由模式获取路由信息
|
|
routeData, ok := getRouteData(url)
|
|
//未注册路由
|
|
if !ok {
|
|
log.Printf("未注册路由:%v", url)
|
|
// log.Printf("routes:%v", common.Routes)
|
|
libs.Error(c, "未注册路由") // 重定向到登录页面
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
if routeData.NeedAuth == 0 { // 过滤附件访问接口
|
|
return
|
|
}
|
|
|
|
token := c.GetHeader("Authorization")
|
|
if routeData.NeedAuth == 3 {
|
|
token = c.GetHeader("AuthorizationAdmin")
|
|
}
|
|
if token == "" {
|
|
token = c.Query("token")
|
|
}
|
|
if token == "" {
|
|
libs.ErrorLogin(c, "token is empty")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
// 验证 token,并存储在请求中
|
|
user, err := libs.ParseToken(token)
|
|
if err != nil {
|
|
libs.ErrorLogin(c, "token is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
session := sessions.Default(c)
|
|
|
|
if routeData.NeedAuth == 1 {
|
|
|
|
clientId := c.GetHeader("ClientID")
|
|
|
|
if clientId == "" {
|
|
clientId = c.Query("uuid")
|
|
if clientId == "" {
|
|
libs.ErrorLogin(c, "clientId is empty")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
}
|
|
if !CheckIp(c.Request) {
|
|
libs.Error(c, "the ip is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
userData, _ := common.Cache.GetKey("userData", clientId)
|
|
if userData == nil {
|
|
libs.ErrorLogin(c, "the userdata is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
m, ok := userData.(map[string]interface{})
|
|
if !ok {
|
|
libs.ErrorLogin(c, "invalid userData type")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
//log.Printf("userData:%v", m)
|
|
userId, ok := m["userId"].(int32)
|
|
if !ok {
|
|
libs.ErrorLogin(c, "userId is not an int64")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
if userId != int32(user.ID) || userId == 0 {
|
|
libs.ErrorLogin(c, "user is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
c.Set("userId", user.ID)
|
|
//log.Printf("userId:%v", user.ID)
|
|
userRoles, ok := m["userRoles"].(string)
|
|
if !ok {
|
|
libs.Error(c, "user roles is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
hasAuth := checkRoles(userRoles, url)
|
|
if !hasAuth {
|
|
libs.Error(c, "user roles check invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
}
|
|
if routeData.NeedAuth == 2 {
|
|
memberId := session.Get("memberId")
|
|
if memberId == nil {
|
|
libs.ErrorLogin(c, "member is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
|
|
uid := getUserId(memberId)
|
|
log.Printf("memberId:%v,uid:%v,user.ID:%v", memberId, uid, user.ID)
|
|
if uid != user.ID || uid == 0 {
|
|
log.Printf("member is invalid")
|
|
libs.ErrorLogin(c, "member is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
c.Set("memberId", uid)
|
|
if uid > 1 {
|
|
memberRoles := session.Get("memberRoles")
|
|
log.Printf("memberRoles:%v", memberRoles)
|
|
if memberRoles == nil {
|
|
libs.Error(c, "member roles is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
memberRole := memberRoles.(string) + ",/index,/member/loginout,/member/welcome,/member/userinfo"
|
|
//log.Printf("adminRules:%v", adminRules)
|
|
hasAuth := checkRoles(memberRole, url)
|
|
if !hasAuth {
|
|
libs.Error(c, "admin roles is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
}
|
|
}
|
|
if routeData.NeedAuth == 3 {
|
|
adminId := session.Get("adminId")
|
|
if adminId == nil {
|
|
libs.ErrorLogin(c, "admin is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
|
|
uid := getUserId(adminId)
|
|
log.Printf("adminId:%v,uid:%v,user.ID:%v", adminId, uid, user.ID)
|
|
if uid != user.ID || uid == 0 {
|
|
log.Printf("admin is invalid")
|
|
libs.ErrorLogin(c, "admin is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
c.Set("adminId", uid)
|
|
if uid > 1 {
|
|
adminRoles := session.Get("adminRoles")
|
|
log.Printf("adminRoles:%v", adminRoles)
|
|
if adminRoles == nil {
|
|
libs.Error(c, "admin roles is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
adminRules := adminRoles.(string) + ",/index,/admin/loginout,/admin/welcome,/admin/userinfo"
|
|
//log.Printf("adminRules:%v", adminRules)
|
|
hasAuth := checkRoles(adminRules, url)
|
|
if !hasAuth {
|
|
libs.Error(c, "admin roles is invalid")
|
|
c.Abort() // 终止后续处理
|
|
return
|
|
}
|
|
}
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
func getRouteData(url string) (Route, bool) {
|
|
for path, route := range Routes {
|
|
// 检查 URL 是否匹配动态路由
|
|
if matchPath(url, path) {
|
|
return route, true
|
|
}
|
|
}
|
|
return Route{}, false
|
|
}
|
|
|
|
// matchPath 检查 URL 是否匹配给定的路径模式
|
|
func matchPath(url, pattern string) bool {
|
|
parts := strings.Split(pattern, "/")
|
|
urlParts := strings.Split(url, "/")
|
|
|
|
if len(parts) != len(urlParts) {
|
|
return false
|
|
}
|
|
//log.Printf("url:%v,pattern:%v", url, pattern)
|
|
if strings.Contains(pattern, ":") {
|
|
for i, part := range parts {
|
|
if part == "" { // 空字符串处理
|
|
continue
|
|
}
|
|
if part[0] == ':' { // 动态参数
|
|
paramName := part[1:]
|
|
if strings.Contains(paramName, "id") { // 数字参数
|
|
if _, err := strconv.Atoi(urlParts[i]); err != nil {
|
|
return false
|
|
}
|
|
}
|
|
} else if part != urlParts[i] { // 静态部分
|
|
return false
|
|
}
|
|
}
|
|
} else {
|
|
if pattern != url {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
func getUserId(userId interface{}) int64 {
|
|
var userIdInt64 int64
|
|
switch v := userId.(type) {
|
|
case int32:
|
|
userIdInt64 = int64(v)
|
|
case int64:
|
|
userIdInt64 = int64(v)
|
|
default: // 终止后续处理
|
|
userIdInt64 = 0
|
|
}
|
|
return userIdInt64
|
|
}
|
|
func checkRoles(rules string, url string) bool {
|
|
if rules == "*" || rules == "-1" {
|
|
return true
|
|
}
|
|
if rules == "" {
|
|
return false
|
|
}
|
|
userRoleArray := strings.Split(rules, ",")
|
|
hasAuth := false
|
|
for _, path := range userRoleArray {
|
|
if matchPath(url, path) {
|
|
hasAuth = true
|
|
break
|
|
}
|
|
}
|
|
return hasAuth
|
|
}
|
|
|
|
// CheckIp 验证客户端 IP 是否允许访问
|
|
func CheckIp(r *http.Request) bool {
|
|
if strings.HasPrefix(r.URL.Scheme, "wails") {
|
|
return true
|
|
}
|
|
|
|
clientIP := r.RemoteAddr
|
|
host := r.Host
|
|
ip, _, err := net.SplitHostPort(clientIP)
|
|
if err != nil {
|
|
//fmt.Printf("Error splitting host and port: %v\n", err)
|
|
return false
|
|
}
|
|
|
|
// 解析 IP 地址
|
|
ipAddress := net.ParseIP(ip)
|
|
//fmt.Printf("clientIP:%v, host:%v\n", clientIP, host)
|
|
|
|
// 允许本机访问
|
|
if ipAddress.IsLoopback() || host == "localhost" {
|
|
return true
|
|
}
|
|
|
|
// 获取允许的 IP 和域名列表
|
|
ipAndDomainList := common.Config.System.IpAccess
|
|
//fmt.Printf("ipAndDomainList:%v\n", ipAndDomainList)
|
|
if len(ipAndDomainList) == 0 {
|
|
return true
|
|
}
|
|
// 检查 IP 地址
|
|
for _, allowed := range ipAndDomainList {
|
|
if ipAddress.String() == allowed {
|
|
return true
|
|
}
|
|
// 检查域名
|
|
if host == allowed {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|