feat(authorization): 添加身份验证中间件和角色条件验证功能- 新增认证中间件组件,支持路径前缀匹配和请求处理管道
- 实现基于正则表达式的URL回退跳转机制 - 添加角色权限验证条件,支持多角色匹配验证 - 集成用户服务注册功能,支持从会话中获取当前用户 - 实现未认证和未授权状态的HTTP响应处理 - 支持配置认证失败时的重定向URL
This commit is contained in:
77
32-platform/platform/authorization/auth_middleware.go
Normal file
77
32-platform/platform/authorization/auth_middleware.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package authorization
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"platform/authorization/identity"
|
||||
"platform/config"
|
||||
"platform/http/handing"
|
||||
"platform/pipeline"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NewAuthComponent(prefix string, condition identity.AuthorizationCondition, requestHandlers ...interface{}) *AuthMiddlewareComponent {
|
||||
var entries []handing.HandlerEntry
|
||||
for _, handler := range requestHandlers {
|
||||
entries = append(entries, handing.HandlerEntry{Prefix: prefix, Handler: handler})
|
||||
}
|
||||
router := handing.NewRouter(entries...)
|
||||
|
||||
return &AuthMiddlewareComponent{
|
||||
prefix: "/" + prefix,
|
||||
condition: condition,
|
||||
RequestPipeline: pipeline.CreatePipeline(router),
|
||||
fallbacks: map[*regexp.Regexp]string{},
|
||||
}
|
||||
}
|
||||
|
||||
type AuthMiddlewareComponent struct {
|
||||
prefix string
|
||||
condition identity.AuthorizationCondition
|
||||
pipeline.RequestPipeline
|
||||
config.Configuration
|
||||
authFailUrl string
|
||||
fallbacks map[*regexp.Regexp]string
|
||||
}
|
||||
|
||||
func (c *AuthMiddlewareComponent) Init() {
|
||||
c.authFailUrl, _ = c.Configuration.GetString("authorization:failUrl")
|
||||
}
|
||||
|
||||
func (c *AuthMiddlewareComponent) ImplementsProcessRequestWithServices() {}
|
||||
|
||||
func (c *AuthMiddlewareComponent) ProcessRequestWithService(context *pipeline.ComponentContext, next func(*pipeline.ComponentContext), user identity.User) {
|
||||
// 匹配前缀
|
||||
if strings.HasPrefix(context.Request.URL.Path, c.prefix) {
|
||||
for expr, target := range c.fallbacks {
|
||||
// 正则表达式匹配,则跳转URL
|
||||
if expr.MatchString(context.Request.URL.Path) {
|
||||
http.Redirect(context.ResponseWriter, context.Request, target, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
}
|
||||
if c.condition.Validate(user) {
|
||||
// 验证通过,则继续处理
|
||||
err := c.RequestPipeline.ProcessRequest(context.Request, context.ResponseWriter)
|
||||
if err != nil {
|
||||
context.Error(err)
|
||||
return
|
||||
}
|
||||
} else if c.authFailUrl != "" {
|
||||
http.Redirect(context.ResponseWriter, context.Request, c.authFailUrl, http.StatusSeeOther)
|
||||
} else if user.IsAuthenticated() {
|
||||
context.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||
} else {
|
||||
context.ResponseWriter.WriteHeader(http.StatusUnauthorized)
|
||||
}
|
||||
} else {
|
||||
next(context)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *AuthMiddlewareComponent) AddFallback(target string, patterns ...string) *AuthMiddlewareComponent {
|
||||
for _, p := range patterns {
|
||||
c.fallbacks[regexp.MustCompile(p)] = target
|
||||
}
|
||||
return c
|
||||
}
|
||||
20
32-platform/platform/authorization/role_condition.go
Normal file
20
32-platform/platform/authorization/role_condition.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package authorization
|
||||
|
||||
import "platform/authorization/identity"
|
||||
|
||||
func NewRoleCondition(roles ...string) identity.AuthorizationCondition {
|
||||
return &roleCondition{allowedRoles: roles}
|
||||
}
|
||||
|
||||
type roleCondition struct {
|
||||
allowedRoles []string
|
||||
}
|
||||
|
||||
func (c *roleCondition) Validate(user identity.User) bool {
|
||||
for _, role := range c.allowedRoles {
|
||||
if user.InRole(role) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
23
32-platform/platform/authorization/user_service.go
Normal file
23
32-platform/platform/authorization/user_service.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package authorization
|
||||
|
||||
import (
|
||||
"platform/authorization/identity"
|
||||
"platform/services"
|
||||
"platform/sessions"
|
||||
)
|
||||
|
||||
func RegisterDefaultUserService() {
|
||||
err := services.AddScoped(func(session sessions.Session, store identity.UserStore) identity.User {
|
||||
userId, found := session.GetValue(UserSessionKey).(int)
|
||||
if found {
|
||||
user, userFound := store.GetUserById(userId)
|
||||
if userFound {
|
||||
return user
|
||||
}
|
||||
}
|
||||
return identity.UnauthenticatedUser
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user