增加简单的安全设置

This commit is contained in:
刘祥超
2020-11-20 18:06:54 +08:00
parent 71feb97c09
commit 8d8460c3fe
9 changed files with 197 additions and 8 deletions

View File

@@ -13,6 +13,4 @@ const (
EncryptMethod = "aes-256-cfb" EncryptMethod = "aes-256-cfb"
ErrServer = "服务器出了点小问题,请联系技术人员处理。" ErrServer = "服务器出了点小问题,请联系技术人员处理。"
EnabledFrame = false // 是否允许被嵌入到别的网站中 TODO 做成可配置
) )

View 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,
}
}

View 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)
}
}

View File

@@ -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()
}

View File

@@ -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()
}) })
} }

View File

@@ -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'")

View File

@@ -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'")

View File

@@ -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>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})