311 lines
9.5 KiB
Go
311 lines
9.5 KiB
Go
package security
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"ems.agt/features/security/service"
|
||
sysConfigService "ems.agt/features/sys_config/service"
|
||
"ems.agt/lib/core/account"
|
||
"ems.agt/lib/core/cache"
|
||
"ems.agt/lib/core/constants/cachekey"
|
||
"ems.agt/lib/core/utils/ctx"
|
||
"ems.agt/lib/core/vo/result"
|
||
"ems.agt/lib/dborm"
|
||
"ems.agt/lib/global"
|
||
"ems.agt/lib/log"
|
||
"ems.agt/lib/oauth"
|
||
"ems.agt/lib/services"
|
||
"ems.agt/restagent/config"
|
||
srcConfig "ems.agt/src/framework/config"
|
||
"ems.agt/src/framework/redis"
|
||
)
|
||
|
||
var (
|
||
UriOauthToken = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||
UriOauthHandshake = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||
|
||
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||
|
||
// 系统登录
|
||
UriLogin = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/login"
|
||
CustomUriLogin = config.UriPrefix + "/securityManagement/{apiVersion}/login"
|
||
|
||
// 获取验证码
|
||
UriCaptchaImage = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
||
CustomUriCaptchaImage = config.UriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
||
|
||
// 登录用户信息
|
||
UriUserInfo = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
||
CustomUriUserInfo = config.UriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
||
|
||
// 登录用户路由信息
|
||
UriRouters = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
||
CustomUriRouters = config.UriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
||
)
|
||
|
||
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||
log.Info("LoginFromOMC processing... ")
|
||
|
||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||
if err != nil {
|
||
log.Error("Failed to ReadAll:", err)
|
||
services.ResponseNotFound404UriNotExist(w, r)
|
||
return
|
||
}
|
||
|
||
// check media type(content type) only support "application/json"
|
||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||
log.Debug("Invalid Content-Type")
|
||
services.ResponseUnsupportedMediaType415(w)
|
||
return
|
||
}
|
||
|
||
// // check extend uri, response 404
|
||
// if !IsValidOAuthUri(r) {
|
||
// log.Debug("Uri is invalid")
|
||
// services.ResponseNotFound404UriNotExist(w, r)
|
||
// return
|
||
// }
|
||
|
||
// Error process ....
|
||
// response 400-7
|
||
if !json.Valid([]byte(body)) {
|
||
log.Error("Invalid Json Format")
|
||
services.ResponseBadRequest400InvalidJson(w)
|
||
return
|
||
}
|
||
|
||
var oAuthBody oauth.OAuthBody
|
||
_ = json.Unmarshal(body, &oAuthBody) //转为json
|
||
//log.Debug("body:", string(body), "oAuthBody:", oAuthBody)
|
||
|
||
defer r.Body.Close()
|
||
// response 400-5
|
||
if oauth.IsWrongOAuthInfo(oAuthBody) {
|
||
log.Error("Wrong parameter value")
|
||
services.ResponseBadRequest400WrongParamValue(w)
|
||
return
|
||
}
|
||
/*
|
||
if oauth.IsValidOAuthInfo(oAuthBody) {
|
||
plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
|
||
log.Debug("Permission list:", plist)
|
||
|
||
token := globalSession.NewSession(w, r, plist)
|
||
services.ResponseStatusOK200Login(w, token)
|
||
} else {
|
||
// response 400-4
|
||
log.Debug("Authentication failed, mismatch user or password")
|
||
|
||
services.ResponseBadRequest400IncorrectLogin(w)
|
||
}
|
||
*/
|
||
validUser, user, err := dborm.XormCheckLoginUser(oAuthBody.UserName,
|
||
oAuthBody.Value, config.GetYamlConfig().Auth.Crypt)
|
||
if !validUser || err != nil {
|
||
// response 400-4
|
||
log.Error("Authentication failed, mismatch user or password")
|
||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||
return
|
||
}
|
||
|
||
token := oauth.GenRandToken("omc") // Generate new token to session ID
|
||
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
||
affected, err := dborm.XormInsertSession(oAuthBody.UserName, sourceAddr, token,
|
||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
||
if err != nil {
|
||
log.Error("Failed to XormInsertSession:", err)
|
||
if affected == -1 {
|
||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
||
} else {
|
||
services.ResponseBadRequest400IncorrectLogin(w)
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
if user != nil {
|
||
// 缓存用户信息
|
||
account.CacheLoginUser(user)
|
||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
||
// 角色权限集合,管理员拥有所有权限
|
||
userId := fmt.Sprint(user.Id)
|
||
isAdmin := srcConfig.IsAdmin(userId)
|
||
roles, perms := service.NewServiceAccount.RoleAndMenuPerms(userId, isAdmin)
|
||
services.ResponseStatusOK200LoginWhitRP(w, token, user, roles, perms)
|
||
return
|
||
}
|
||
services.ResponseBadRequest400IncorrectLogin(w)
|
||
}
|
||
|
||
func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
|
||
log.Info("LogoutFromOMC processing... ")
|
||
|
||
token, err := services.CheckFrontValidRequest(w, r)
|
||
if err != nil {
|
||
log.Error("Request error:", err)
|
||
return
|
||
}
|
||
// // check media type(content type) only support "application/json"
|
||
// if services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) == false {
|
||
// log.Error("Invalid Content-Type")
|
||
// services.ResponseUnsupportedMediaType415(w)
|
||
// return
|
||
// }
|
||
|
||
// // check extend uri, response 404
|
||
// if !services.IsValidOAuthUri(r) {
|
||
// log.Error("Uri is invalid")
|
||
// services.ResponseNotFound404UriNotExist(w, r)
|
||
// return
|
||
// }
|
||
|
||
// // error processing ...
|
||
// // 401-1 response
|
||
// token, ret := oauth.IsCarriedToken(r)
|
||
// if ret == false {
|
||
// log.Error("AccessToken is not carried")
|
||
// services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||
// return
|
||
// }
|
||
|
||
se, err := dborm.XormLogoutUpdateSession(token)
|
||
if err != nil {
|
||
log.Error("Uri is invalid")
|
||
services.ResponseNotFound404UriNotExist(w, r)
|
||
return
|
||
}
|
||
// 清除缓存用户信息
|
||
account.ClearLoginUser(se.AccountId)
|
||
services.ResponseStatusOK200Null(w)
|
||
}
|
||
|
||
func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
|
||
log.Info("HandshakeFromOMC processing... ")
|
||
|
||
// check media type(content type) only support "application/json"
|
||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||
log.Debug("Invalid Content-Type")
|
||
services.ResponseUnsupportedMediaType415(w)
|
||
return
|
||
}
|
||
|
||
// check extend uri, response 404
|
||
if !services.IsValidOAuthUri(r) {
|
||
log.Error("Uri is invalid")
|
||
services.ResponseNotFound404UriNotExist(w, r)
|
||
return
|
||
}
|
||
|
||
// error processing ...
|
||
// 401-1 response
|
||
token, ret := oauth.IsCarriedToken(r)
|
||
if !ret {
|
||
log.Error("AccessToken is not carried")
|
||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||
return
|
||
}
|
||
|
||
_, err := dborm.XormUpdateSessionShakeTime(token)
|
||
if err != nil {
|
||
log.Error("Uri is invalid")
|
||
services.ResponseNotFound404UriNotExist(w, r)
|
||
return
|
||
}
|
||
services.ResponseStatusOK200Null(w)
|
||
}
|
||
|
||
// 系统登录
|
||
//
|
||
// POST /login
|
||
func LoginOMC(w http.ResponseWriter, r *http.Request) {
|
||
log.Info("LoginOMC processing... ")
|
||
var body struct {
|
||
Username string `json:"username" binding:"required"` // Username 用户名
|
||
Password string `json:"password" binding:"required"` // Password 用户密码
|
||
Code string `json:"code"` // Code 验证码
|
||
UUID string `json:"uuid"` // UUID 验证码唯一标识
|
||
}
|
||
err := ctx.ShouldBindJSON(r, &body)
|
||
if err != nil {
|
||
log.Error("Invalid Json Format")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||
return
|
||
}
|
||
// response 400-5
|
||
if body.Username == "" || body.Password == "" {
|
||
log.Error("Wrong parameter value")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||
return
|
||
}
|
||
|
||
// 校验验证码
|
||
// 从数据库配置获取验证码开关 true开启,false关闭
|
||
captchaEnabledStr := sysConfigService.NewServiceSysConfig.SelectConfigValueByKey("sys.account.captchaEnabled")
|
||
captchaEnabled, err := strconv.ParseBool(captchaEnabledStr)
|
||
if err != nil {
|
||
captchaEnabled = false
|
||
}
|
||
if captchaEnabled {
|
||
if body.Code == "" || body.UUID == "" {
|
||
log.Error("Authentication failed, mismatch captcha")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code information error"))
|
||
return
|
||
}
|
||
verifyKey := cachekey.CAPTCHA_CODE_KEY + body.UUID
|
||
captcha, ok := cache.GetLocalTTL(verifyKey)
|
||
if captcha == nil || !ok {
|
||
log.Error("Authentication failed, captcha emtry")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, "The verification code has expired"))
|
||
return
|
||
}
|
||
cache.DeleteLocalTTL(verifyKey)
|
||
if captcha.(string) != body.Code {
|
||
log.Error("Authentication failed, not match captcha")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code error"))
|
||
return
|
||
}
|
||
}
|
||
|
||
validUser, user, err := dborm.XormCheckLoginUser(body.Username, body.Password, config.GetYamlConfig().Auth.Crypt)
|
||
if !validUser || err != nil {
|
||
// response 400-4
|
||
log.Error("Authentication failed, mismatch user or password")
|
||
ctx.JSON(w, 400, result.CodeMsg(400, err.Error()))
|
||
return
|
||
}
|
||
|
||
token := oauth.GenRandToken("omc") // Generate new token to session ID
|
||
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
||
affected, err := dborm.XormInsertSession(body.Username, sourceAddr, token,
|
||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
||
if err != nil {
|
||
log.Error("Failed to XormInsertSession:", err)
|
||
if affected == -1 {
|
||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
||
} else {
|
||
services.ResponseBadRequest400IncorrectLogin(w)
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
if user != nil {
|
||
// 缓存用户信息
|
||
account.CacheLoginUser(user)
|
||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||
"accessToken": token,
|
||
}))
|
||
return
|
||
}
|
||
ctx.JSON(w, 200, result.Err(nil))
|
||
}
|