feat: 客户端oauth2认证模块
This commit is contained in:
@@ -17,7 +17,6 @@ import (
|
||||
networkelement "be.ems/src/modules/network_element"
|
||||
"be.ems/src/modules/notification"
|
||||
"be.ems/src/modules/oam"
|
||||
"be.ems/src/modules/oauth2"
|
||||
"be.ems/src/modules/system"
|
||||
"be.ems/src/modules/tool"
|
||||
"be.ems/src/modules/trace"
|
||||
@@ -84,10 +83,9 @@ func ModulesRoute(app *gin.Engine) {
|
||||
system.Setup(app)
|
||||
// 认证模块
|
||||
auth.Setup(app)
|
||||
// 开放客户端模块
|
||||
oauth2.Setup(app)
|
||||
// 网元OAM对接
|
||||
oam.Setup(app)
|
||||
oam.SetupOauth2(app)
|
||||
// 通用模块
|
||||
common.Setup(app)
|
||||
|
||||
|
||||
@@ -116,4 +116,62 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
}
|
||||
|
||||
// 客户端授权管理
|
||||
oauth2Client := controller.NewOauth2Client
|
||||
oauth2ClientGroup := router.Group("/oauth2/client")
|
||||
{
|
||||
oauth2ClientGroup.GET("/list",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
oauth2Client.List,
|
||||
)
|
||||
oauth2ClientGroup.GET("/:clientId",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
oauth2Client.Info,
|
||||
)
|
||||
oauth2ClientGroup.POST("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_INSERT)),
|
||||
oauth2Client.Add,
|
||||
)
|
||||
oauth2ClientGroup.PUT("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_UPDATE)),
|
||||
oauth2Client.Edit,
|
||||
)
|
||||
oauth2ClientGroup.DELETE("/:id",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_DELETE)),
|
||||
oauth2Client.Remove,
|
||||
)
|
||||
}
|
||||
|
||||
// 授权认证
|
||||
oauth2 := controller.NewOauth2
|
||||
oauth2Group := router.Group("/oauth2")
|
||||
{
|
||||
oauth2Group.GET("/authorize",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 30,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.Authorize,
|
||||
)
|
||||
oauth2Group.POST("/token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.Token,
|
||||
)
|
||||
oauth2Group.POST("/refresh-token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 5,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.RefreshToken,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/service"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/service"
|
||||
)
|
||||
|
||||
// NewOauth2 实例化控制层
|
||||
168
src/modules/auth/controller/oauth2_client.go
Normal file
168
src/modules/auth/controller/oauth2_client.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/service"
|
||||
)
|
||||
|
||||
// NewOauth2Client 实例化控制层
|
||||
var NewOauth2Client = &Oauth2ClientController{
|
||||
oauth2ClientService: service.NewOauth2ClientService,
|
||||
}
|
||||
|
||||
// Oauth2ClientController 客户端授权管理 控制层处理
|
||||
//
|
||||
// PATH /oauth2/client
|
||||
type Oauth2ClientController struct {
|
||||
oauth2ClientService *service.Oauth2ClientService // 用户授权第三方应用信息服务
|
||||
}
|
||||
|
||||
// List 列表
|
||||
//
|
||||
// GET /list
|
||||
func (s Oauth2ClientController) List(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
rows, total := s.oauth2ClientService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
// Info 信息
|
||||
//
|
||||
// GET /:clientId
|
||||
func (s Oauth2ClientController) Info(c *gin.Context) {
|
||||
clientId := c.Param("clientId")
|
||||
if clientId == "" {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: clientId is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
info := s.oauth2ClientService.FindByClientId(clientId)
|
||||
if info.ClientId == clientId {
|
||||
c.JSON(200, resp.OkData(info))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.ErrMsg("clientId does not exist"))
|
||||
}
|
||||
|
||||
// Add 新增
|
||||
//
|
||||
// POST /
|
||||
func (s Oauth2ClientController) Add(c *gin.Context) {
|
||||
var body model.Oauth2Client
|
||||
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
if body.Id > 0 {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id not is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
// 本地IP地址不支持
|
||||
localHosts := []string{"127.0.0.1", "localhost", "::ffff:", "::1"}
|
||||
localHost := false
|
||||
for _, host := range localHosts {
|
||||
if strings.Contains(body.IPWhite, host) {
|
||||
localHost = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if localHost {
|
||||
c.JSON(200, resp.ErrMsg("no support local host"))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = reqctx.LoginUserToUserName(c)
|
||||
insertId := s.oauth2ClientService.Insert(body)
|
||||
if insertId > 0 {
|
||||
c.JSON(200, resp.OkData(insertId))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Err(nil))
|
||||
}
|
||||
|
||||
// Edit 更新
|
||||
//
|
||||
// PUT /
|
||||
func (s Oauth2ClientController) Edit(c *gin.Context) {
|
||||
var body model.Oauth2Client
|
||||
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
if body.Id <= 0 {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
// 本地IP地址不支持
|
||||
localHosts := []string{"127.0.0.1", "localhost", "::ffff:", "::1"}
|
||||
localHost := false
|
||||
for _, host := range localHosts {
|
||||
if strings.Contains(body.IPWhite, host) {
|
||||
localHost = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if localHost {
|
||||
c.JSON(200, resp.ErrMsg("no support local host"))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询信息
|
||||
info := s.oauth2ClientService.FindById(body.Id)
|
||||
if info.ClientId == "" || info.Id != body.Id {
|
||||
c.JSON(200, resp.ErrMsg("modification failed, data not exist"))
|
||||
return
|
||||
}
|
||||
|
||||
info.Title = body.Title
|
||||
info.IPWhite = body.IPWhite
|
||||
info.Remark = body.Remark
|
||||
info.UpdateBy = reqctx.LoginUserToUserName(c)
|
||||
rowsAffected := s.oauth2ClientService.Update(info)
|
||||
if rowsAffected > 0 {
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Err(nil))
|
||||
}
|
||||
|
||||
// Remove 删除
|
||||
//
|
||||
// DELETE /:id
|
||||
func (s Oauth2ClientController) Remove(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
|
||||
// 转换成int64数组类型
|
||||
ids := make([]int64, 0)
|
||||
for _, v := range uniqueIDs {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.oauth2ClientService.DeleteByIds(ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, resp.OkMsg(msg))
|
||||
}
|
||||
@@ -8,3 +8,10 @@ type TokenBody struct {
|
||||
Code string `json:"code"` // 授权拿到的code值
|
||||
RefreshToken string `json:"refreshToken"` // 刷新令牌
|
||||
}
|
||||
|
||||
// CodeQuery 重定向授权码参数
|
||||
type CodeQuery struct {
|
||||
RedirectUrl string `form:"redirectUrl" binding:"required"` // 授权回调地址
|
||||
ClientId string `form:"clientId" binding:"required"` // 申请得到的客户端ID
|
||||
State string `form:"state" binding:"required"` // 随机字符串,认证服务器会原封不动地返回这个值
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/auth/model"
|
||||
)
|
||||
|
||||
// NewOauth2Client 实例化数据层
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/auth/model"
|
||||
)
|
||||
|
||||
// NewOauth2LogLogin 实例化数据层
|
||||
@@ -69,9 +69,10 @@ func (r Oauth2LogLoginRepository) SelectByPage(query map[string]string) ([]model
|
||||
sortOrder := sortOrderArr[i]
|
||||
// 排序字段
|
||||
sort := "id"
|
||||
if sortBy == "loginIp" {
|
||||
switch sortBy {
|
||||
case "loginIp":
|
||||
sort = "login_ip"
|
||||
} else if sortBy == "createTime" {
|
||||
case "createTime":
|
||||
sort = "create_time"
|
||||
}
|
||||
// 排序方式
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/crypto"
|
||||
"be.ems/src/framework/utils/generate"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2Service 实例化服务层
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/utils/generate"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2ClientService 实例化服务层
|
||||
@@ -55,11 +55,11 @@ func (s Oauth2ClientService) DeleteByIds(ids []int64) (int64, error) {
|
||||
arr := s.oauth2ClientRepository.SelectByIds(ids)
|
||||
if len(arr) <= 0 {
|
||||
// return 0, fmt.Errorf("没有权限访问用户授权第三方应用数据!")
|
||||
return 0, fmt.Errorf("No permission to access user-authorized third-party application data!")
|
||||
return 0, fmt.Errorf("no permission to access user-authorized third-party application data")
|
||||
}
|
||||
if len(arr) == len(ids) {
|
||||
return s.oauth2ClientRepository.DeleteByIds(ids), nil
|
||||
}
|
||||
// return 0, fmt.Errorf("删除用户授权第三方应用信息失败!")
|
||||
return 0, fmt.Errorf("Failed to delete user-authorized third-party application information!")
|
||||
return 0, fmt.Errorf("failed to delete user-authorized third-party application information")
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2LogLogin 实例化服务层
|
||||
@@ -1,4 +1,4 @@
|
||||
package oauth2
|
||||
package oam
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
neController "be.ems/src/modules/network_element/controller"
|
||||
)
|
||||
|
||||
// openAPI 客户端授权开放接口
|
||||
func openAPI(router *gin.Engine) {
|
||||
// SetupOauth2 客户端授权开放接口
|
||||
func SetupOauth2(router *gin.Engine) {
|
||||
openApiGroup := router.Group("/open-api")
|
||||
|
||||
// 监控
|
||||
@@ -1,8 +0,0 @@
|
||||
package model
|
||||
|
||||
// CodeQuery 重定向授权码参数
|
||||
type CodeQuery struct {
|
||||
RedirectUrl string `form:"redirectUrl" binding:"required"` // 授权回调地址
|
||||
ClientId string `form:"clientId" binding:"required"` // 申请得到的客户端ID
|
||||
State string `form:"state" binding:"required"` // 随机字符串,认证服务器会原封不动地返回这个值
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package oauth2
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/src/modules/oauth2/controller"
|
||||
)
|
||||
|
||||
// Setup 模块路由注册
|
||||
func Setup(router *gin.Engine) {
|
||||
logger.Infof("开始加载 ====> oauth2 模块路由")
|
||||
|
||||
// 客户端授权管理
|
||||
oauth2ClientGroup := router.Group("/oauth2/client")
|
||||
{
|
||||
oauth2ClientGroup.GET("/list",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
controller.NewOauth2Client.List,
|
||||
)
|
||||
oauth2ClientGroup.GET("/:clientId",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
controller.NewOauth2Client.Info,
|
||||
)
|
||||
oauth2ClientGroup.POST("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewOauth2Client.Add,
|
||||
)
|
||||
oauth2ClientGroup.PUT("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewOauth2Client.Edit,
|
||||
)
|
||||
oauth2ClientGroup.DELETE("/:id",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewOauth2Client.Remove,
|
||||
)
|
||||
}
|
||||
|
||||
// 授权认证
|
||||
oauth2Group := router.Group("/oauth2")
|
||||
{
|
||||
oauth2Group.GET("/authorize",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 30,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewOauth2.Authorize,
|
||||
)
|
||||
oauth2Group.POST("/token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewOauth2.Token,
|
||||
)
|
||||
oauth2Group.POST("/refresh-token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 5,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewOauth2.RefreshToken,
|
||||
)
|
||||
}
|
||||
|
||||
// ==== 授权认证的开放接口 ====
|
||||
openAPI(router)
|
||||
}
|
||||
Reference in New Issue
Block a user