mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-15 04:41:25 +08:00
增加简单的安全设置
This commit is contained in:
@@ -13,6 +13,4 @@ const (
|
||||
EncryptMethod = "aes-256-cfb"
|
||||
|
||||
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
|
||||
|
||||
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 {
|
||||
actionutils.ParentAction
|
||||
@@ -11,5 +15,35 @@ func (this *IndexAction) Init() {
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
config, err := securitymanager.LoadSecurityConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["config"] = config
|
||||
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(settingutils.NewHelper("security")).
|
||||
Prefix("/settings/security").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package helpers
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/securitymanager"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -26,8 +27,11 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
||||
var action = actionPtr.Object()
|
||||
|
||||
// 安全相关
|
||||
if !teaconst.EnabledFrame {
|
||||
securityConfig, _ := securitymanager.LoadSecurityConfig()
|
||||
if securityConfig == nil {
|
||||
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'")
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/securitymanager"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/http"
|
||||
@@ -16,8 +16,11 @@ func (this *UserShouldAuth) BeforeAction(actionPtr actions.ActionWrapper, paramN
|
||||
|
||||
// 安全相关
|
||||
action := this.action
|
||||
if !teaconst.EnabledFrame {
|
||||
securityConfig, _ := securitymanager.LoadSecurityConfig()
|
||||
if securityConfig == nil {
|
||||
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'")
|
||||
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
{$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