mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-03 12:20:28 +08:00
管理系统安全设置增加“自定义客户端IP报头”
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/index/loginutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
@@ -106,7 +107,7 @@ func (this *ParentAction) CreateLog(level string, messageCode langs.MessageCode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := dao.SharedLogDAO.CreateAdminLog(this.AdminContext(), level, this.Request.URL.Path, desc, this.RequestRemoteIP(), messageCode, args)
|
err := dao.SharedLogDAO.CreateAdminLog(this.AdminContext(), level, this.Request.URL.Path, desc, loginutils.RemoteIP(&this.ActionObject), messageCode, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(0), oplogs.LevelError, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogSystemError, err.Error()), this.RequestRemoteIP(), codes.AdminLogin_LogSystemError, []any{err.Error()})
|
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(0), oplogs.LevelError, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogSystemError, err.Error()), loginutils.RemoteIP(&this.ActionObject), codes.AdminLogin_LogSystemError, []any{err.Error()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !resp.IsOk {
|
if !resp.IsOk {
|
||||||
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(0), oplogs.LevelWarn, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogFailed, params.Username), this.RequestRemoteIP(), codes.AdminLogin_LogFailed, []any{params.Username})
|
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(0), oplogs.LevelWarn, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogFailed, params.Username), loginutils.RemoteIP(&this.ActionObject), codes.AdminLogin_LogFailed, []any{params.Username})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
}
|
}
|
||||||
@@ -225,7 +225,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
params.Auth.StoreAdmin(adminId, params.Remember)
|
params.Auth.StoreAdmin(adminId, params.Remember)
|
||||||
|
|
||||||
// 记录日志
|
// 记录日志
|
||||||
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(adminId), oplogs.LevelInfo, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogSuccess, params.Username), this.RequestRemoteIP(), codes.AdminLogin_LogSuccess, []any{params.Username})
|
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(adminId), oplogs.LevelInfo, this.Request.URL.Path, langs.DefaultMessage(codes.AdminLogin_LogSuccess, params.Username), loginutils.RemoteIP(&this.ActionObject), codes.AdminLogin_LogSuccess, []any{params.Username})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
}
|
}
|
||||||
@@ -235,7 +235,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
|
|
||||||
// 检查登录区域
|
// 检查登录区域
|
||||||
func (this *IndexAction) checkRegion() bool {
|
func (this *IndexAction) checkRegion() bool {
|
||||||
var ip = this.RequestRemoteIP()
|
var ip = loginutils.RemoteIP(&this.ActionObject)
|
||||||
var result = iplibrary.LookupIP(ip)
|
var result = iplibrary.LookupIP(ip)
|
||||||
if result != nil && result.IsOk() && result.CountryId() > 0 && lists.ContainsInt64([]int64{9, 10}, result.CountryId()) {
|
if result != nil && result.IsOk() && result.CountryId() > 0 && lists.ContainsInt64([]int64{9, 10}, result.CountryId()) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
package loginutils
|
package loginutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CalculateClientFingerprint 计算客户端指纹
|
// CalculateClientFingerprint 计算客户端指纹
|
||||||
@@ -17,8 +20,26 @@ func CalculateClientFingerprint(action *actions.ActionObject) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoteIP 获取客户端IP
|
// RemoteIP 获取客户端IP
|
||||||
// TODO 将来增加是否使用代理设置(即从X-Real-IP中获取IP)
|
|
||||||
func RemoteIP(action *actions.ActionObject) string {
|
func RemoteIP(action *actions.ActionObject) string {
|
||||||
|
securityConfig, _ := configloaders.LoadSecurityConfig()
|
||||||
|
|
||||||
|
if securityConfig != nil {
|
||||||
|
if len(securityConfig.ClientIPHeaderNames) > 0 {
|
||||||
|
var headerNames = regexp.MustCompile(`[,;\s,、;]`).Split(securityConfig.ClientIPHeaderNames, -1)
|
||||||
|
for _, headerName := range headerNames {
|
||||||
|
headerName = http.CanonicalHeaderKey(strings.TrimSpace(headerName))
|
||||||
|
if len(headerName) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipValue = action.Request.Header.Get(headerName)
|
||||||
|
if net.ParseIP(ipValue) != nil {
|
||||||
|
return ipValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ip, _, _ := net.SplitHostPort(action.Request.RemoteAddr)
|
ip, _, _ := net.SplitHostPort(action.Request.RemoteAddr)
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"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/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/index/loginutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
@@ -146,7 +147,7 @@ func (this *OtpAction) RunPost(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(adminId), oplogs.LevelInfo, this.Request.URL.Path, this.Lang(codes.AdminLogin_LogOtpVerifiedSuccess), this.RequestRemoteIP(), codes.AdminLogin_LogOtpVerifiedSuccess, nil)
|
err = dao.SharedLogDAO.CreateAdminLog(rpcClient.Context(adminId), oplogs.LevelInfo, this.Request.URL.Path, this.Lang(codes.AdminLogin_LogOtpVerifiedSuccess), loginutils.RemoteIP(&this.ActionObject), codes.AdminLogin_LogOtpVerifiedSuccess, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
AllowIPs []string
|
AllowIPs []string
|
||||||
AllowRememberLogin bool
|
AllowRememberLogin bool
|
||||||
|
|
||||||
|
ClientIPHeaderNames string
|
||||||
|
|
||||||
DenySearchEngines bool
|
DenySearchEngines bool
|
||||||
DenySpiders bool
|
DenySpiders bool
|
||||||
|
|
||||||
@@ -137,6 +139,9 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
// 允许本地
|
// 允许本地
|
||||||
config.AllowLocal = params.AllowLocal
|
config.AllowLocal = params.AllowLocal
|
||||||
|
|
||||||
|
// 客户端IP获取方式
|
||||||
|
config.ClientIPHeaderNames = params.ClientIPHeaderNames
|
||||||
|
|
||||||
// 禁止搜索引擎和爬虫
|
// 禁止搜索引擎和爬虫
|
||||||
config.DenySearchEngines = params.DenySearchEngines
|
config.DenySearchEngines = params.DenySearchEngines
|
||||||
config.DenySpiders = params.DenySpiders
|
config.DenySpiders = params.DenySpiders
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -145,12 +144,7 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
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'")
|
||||||
|
|
||||||
// 检查IP
|
// 检查IP
|
||||||
if !checkIP(securityConfig, action.RequestRemoteIP()) {
|
if !checkIP(securityConfig, loginutils.RemoteIP(action)) {
|
||||||
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
remoteAddr, _, _ := net.SplitHostPort(action.Request.RemoteAddr)
|
|
||||||
if len(remoteAddr) > 0 && remoteAddr != action.RequestRemoteIP() && !checkIP(securityConfig, remoteAddr) {
|
|
||||||
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/index/loginutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/index/loginutils"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,12 +32,7 @@ func (this *UserShouldAuth) BeforeAction(actionPtr actions.ActionWrapper, paramN
|
|||||||
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'")
|
||||||
|
|
||||||
// 检查IP
|
// 检查IP
|
||||||
if !checkIP(securityConfig, action.RequestRemoteIP()) {
|
if !checkIP(securityConfig, loginutils.RemoteIP(action)) {
|
||||||
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
remoteAddr, _, _ := net.SplitHostPort(action.Request.RemoteAddr)
|
|
||||||
if len(remoteAddr) > 0 && remoteAddr != action.RequestRemoteIP() && !checkIP(securityConfig, remoteAddr) {
|
|
||||||
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
action.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
|
|
||||||
<div class="margin"></div>
|
<div class="margin"></div>
|
||||||
|
<p class="comment">当前安全设置只适用于管理系统,对用户网站没有任何影响。</p>
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
@@ -56,6 +57,13 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tbody v-show="moreOptionsVisible">
|
<tbody v-show="moreOptionsVisible">
|
||||||
|
<tr>
|
||||||
|
<td>自定义客户端IP报头</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="clientIPHeaderNames" v-model="config.clientIPHeaderNames"/>
|
||||||
|
<p class="comment">可以通过此报头获取客户端IP,类似于<code-label>Client-IP</code-label>,用于使用反向代理访问管理系统的情形;如果有多个报头可以使用空格隔开。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>禁止搜索引擎</td>
|
<td>禁止搜索引擎</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否显示底部开源信息</td>
|
<td>显示底部开源信息</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="showOpenSourceInfo" v-model="config.showOpenSourceInfo"></checkbox>
|
<checkbox name="showOpenSourceInfo" v-model="config.showOpenSourceInfo"></checkbox>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否显示版本号</td>
|
<td>显示版本号</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="showVersion" v-model="config.showVersion"></checkbox>
|
<checkbox name="showVersion" v-model="config.showVersion"></checkbox>
|
||||||
<p class="comment">选中后,在界面中显示系统版本号。</p>
|
<p class="comment">选中后,在界面中显示系统版本号。</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user