1
0
Files
omc_api/features/security/account.go
2024-01-12 11:54:25 +08:00

311 lines
9.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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))
}