mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-14 20:30:25 +08:00
增加简单的安全设置
This commit is contained in:
@@ -13,6 +13,4 @@ const (
|
|||||||
EncryptMethod = "aes-256-cfb"
|
EncryptMethod = "aes-256-cfb"
|
||||||
|
|
||||||
ErrServer = "服务器出了点小问题,请联系技术人员处理。"
|
ErrServer = "服务器出了点小问题,请联系技术人员处理。"
|
||||||
|
|
||||||
EnabledFrame = false // 是否允许被嵌入到别的网站中 TODO 做成可配置
|
|
||||||
)
|
)
|
||||||
|
|||||||
98
internal/securitymanager/security_config.go
Normal file
98
internal/securitymanager/security_config.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package securitymanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var locker sync.Mutex
|
||||||
|
|
||||||
|
const (
|
||||||
|
SecuritySettingName = "adminSecurityConfig"
|
||||||
|
|
||||||
|
FrameNone = ""
|
||||||
|
FrameDeny = "DENY"
|
||||||
|
FrameSameOrigin = "SAMEORIGIN"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sharedSecurityConfig *SecurityConfig = nil
|
||||||
|
|
||||||
|
type SecurityConfig struct {
|
||||||
|
Frame string `json:"frame"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSecurityConfig() (*SecurityConfig, error) {
|
||||||
|
locker.Lock()
|
||||||
|
defer locker.Unlock()
|
||||||
|
|
||||||
|
config, err := loadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(config)).Interface().(SecurityConfig)
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateSecurityConfig(securityConfig *SecurityConfig) error {
|
||||||
|
locker.Lock()
|
||||||
|
defer locker.Unlock()
|
||||||
|
|
||||||
|
var rpcClient, err = rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
valueJSON, err := json.Marshal(securityConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = rpcClient.SysSettingRPC().UpdateSysSetting(rpcClient.Context(1), &pb.UpdateSysSettingRequest{
|
||||||
|
Code: SecuritySettingName,
|
||||||
|
ValueJSON: valueJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sharedSecurityConfig = securityConfig
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSecurityConfig() (*SecurityConfig, error) {
|
||||||
|
if sharedSecurityConfig != nil {
|
||||||
|
return sharedSecurityConfig, nil
|
||||||
|
}
|
||||||
|
var rpcClient, err = rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := rpcClient.SysSettingRPC().ReadSysSetting(rpcClient.Context(1), &pb.ReadSysSettingRequest{
|
||||||
|
Code: SecuritySettingName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.ValueJSON) == 0 {
|
||||||
|
sharedSecurityConfig = defaultSecurityConfig()
|
||||||
|
return sharedSecurityConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &SecurityConfig{}
|
||||||
|
err = json.Unmarshal(resp.ValueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
logs.Println("[SECURITY_MANAGER]" + err.Error())
|
||||||
|
sharedSecurityConfig = defaultSecurityConfig()
|
||||||
|
return sharedSecurityConfig, nil
|
||||||
|
}
|
||||||
|
sharedSecurityConfig = config
|
||||||
|
return sharedSecurityConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultSecurityConfig() *SecurityConfig {
|
||||||
|
return &SecurityConfig{
|
||||||
|
Frame: FrameSameOrigin,
|
||||||
|
}
|
||||||
|
}
|
||||||
32
internal/securitymanager/security_config_test.go
Normal file
32
internal/securitymanager/security_config_test.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package securitymanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadSecurityConfig(t *testing.T) {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
before := time.Now()
|
||||||
|
config, err := LoadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||||
|
t.Logf("%p", config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadSecurityConfig2(t *testing.T) {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
config, err := LoadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
config.Frame = "DENY"
|
||||||
|
}
|
||||||
|
t.Log(config.Frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package security
|
package security
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/securitymanager"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
@@ -11,5 +15,35 @@ func (this *IndexAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
config, err := securitymanager.LoadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["config"] = config
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
Frame string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改管理界面安全设置")
|
||||||
|
|
||||||
|
config, err := securitymanager.LoadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Frame = params.Frame
|
||||||
|
err = securitymanager.UpdateSecurityConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func init() {
|
|||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(settingutils.NewHelper("security")).
|
Helper(settingutils.NewHelper("security")).
|
||||||
Prefix("/settings/security").
|
Prefix("/settings/security").
|
||||||
Get("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package helpers
|
|||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/securitymanager"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -26,8 +27,11 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
var action = actionPtr.Object()
|
var action = actionPtr.Object()
|
||||||
|
|
||||||
// 安全相关
|
// 安全相关
|
||||||
if !teaconst.EnabledFrame {
|
securityConfig, _ := securitymanager.LoadSecurityConfig()
|
||||||
|
if securityConfig == nil {
|
||||||
action.AddHeader("X-Frame-Options", "SAMEORIGIN")
|
action.AddHeader("X-Frame-Options", "SAMEORIGIN")
|
||||||
|
} else if len(securityConfig.Frame) > 0 {
|
||||||
|
action.AddHeader("X-Frame-Options", securityConfig.Frame)
|
||||||
}
|
}
|
||||||
action.AddHeader("Content-Security-Policy", "default-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'")
|
action.AddHeader("Content-Security-Policy", "default-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
"github.com/TeaOSLab/EdgeAdmin/internal/securitymanager"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -16,8 +16,11 @@ func (this *UserShouldAuth) BeforeAction(actionPtr actions.ActionWrapper, paramN
|
|||||||
|
|
||||||
// 安全相关
|
// 安全相关
|
||||||
action := this.action
|
action := this.action
|
||||||
if !teaconst.EnabledFrame {
|
securityConfig, _ := securitymanager.LoadSecurityConfig()
|
||||||
|
if securityConfig == nil {
|
||||||
action.AddHeader("X-Frame-Options", "SAMEORIGIN")
|
action.AddHeader("X-Frame-Options", "SAMEORIGIN")
|
||||||
|
} else if len(securityConfig.Frame) > 0 {
|
||||||
|
action.AddHeader("X-Frame-Options", securityConfig.Frame)
|
||||||
}
|
}
|
||||||
action.AddHeader("Content-Security-Policy", "default-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'")
|
action.AddHeader("Content-Security-Policy", "default-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'")
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
|
|
||||||
<p class="comment">此功能暂未开放,敬请期待。</p>
|
<div class="margin"></div>
|
||||||
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">Frame嵌套条件</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="frame" v-model="config.frame">
|
||||||
|
<option value="">不限制</option>
|
||||||
|
<option value="SAMEORIGIN">仅限同域名</option>
|
||||||
|
<option value="DENY">完全禁止</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">当前服务被别的网页框架嵌套的条件限制。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
3
web/views/@default/settings/security/index.js
Normal file
3
web/views/@default/settings/security/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyReloadSuccess("保存成功")
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user