feat: 修改安全入口页特征样式 (#5159)

pull/5164/head
ssongliu 2024-05-27 11:32:54 +08:00 committed by GitHub
parent 41bc8b634b
commit c39f029808
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 187 additions and 172 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/middleware"
"github.com/1Panel-dev/1Panel/backend/utils/captcha" "github.com/1Panel-dev/1Panel/backend/utils/captcha"
"github.com/1Panel-dev/1Panel/backend/utils/qqwry" "github.com/1Panel-dev/1Panel/backend/utils/qqwry"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -113,21 +114,12 @@ func (b *BaseApi) Captcha(c *gin.Context) {
// @Router /auth/issafety [get] // @Router /auth/issafety [get]
func (b *BaseApi) CheckIsSafety(c *gin.Context) { func (b *BaseApi) CheckIsSafety(c *gin.Context) {
code := c.DefaultQuery("code", "") code := c.DefaultQuery("code", "")
status, err := authService.CheckIsSafety(code) isSafe := authService.CheckIsSafety(code)
if err != nil { if !isSafe {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrResponse(c, middleware.LoadErrCode("err-entrance"))
return return
} }
helper.SuccessWithData(c, status) helper.SuccessWithOutData(c)
}
func (b *BaseApi) GetResponsePage(c *gin.Context) {
pageCode, err := authService.GetResponsePage()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, pageCode)
} }
// @Tags Auth // @Tags Auth

View File

@ -133,3 +133,8 @@ func CheckBind(req interface{}, c *gin.Context) error {
} }
return nil return nil
} }
func ErrResponse(ctx *gin.Context, code int) {
ctx.JSON(code, nil)
ctx.Abort()
}

View File

@ -19,8 +19,7 @@ import (
type AuthService struct{} type AuthService struct{}
type IAuthService interface { type IAuthService interface {
CheckIsSafety(code string) (string, error) CheckIsSafety(code string) bool
GetResponsePage() (string, error)
VerifyCode(code string) (bool, error) VerifyCode(code string) (bool, error)
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error) Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error)
LogOut(c *gin.Context) error LogOut(c *gin.Context) error
@ -173,24 +172,16 @@ func (u *AuthService) VerifyCode(code string) (bool, error) {
return hmac.Equal([]byte(setting.Value), []byte(code)), nil return hmac.Equal([]byte(setting.Value), []byte(code)), nil
} }
func (u *AuthService) CheckIsSafety(code string) (string, error) { func (u *AuthService) CheckIsSafety(code string) bool {
status, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance")) status, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
if err != nil { if err != nil {
return "", err return true
} }
if len(status.Value) == 0 { if len(status.Value) == 0 {
return "disable", nil return true
} }
if status.Value == code { if status.Value == code {
return "pass", nil return true
} }
return "unpass", nil return false
}
func (u *AuthService) GetResponsePage() (string, error) {
pageCode, err := settingRepo.Get(settingRepo.WithByKey("NoAuthSetting"))
if err != nil {
return "", err
}
return pageCode.Value, nil
} }

View File

@ -8,16 +8,14 @@ const (
CodeSuccess = 200 CodeSuccess = 200
CodeErrBadRequest = 400 CodeErrBadRequest = 400
CodeErrUnauthorized = 401 CodeErrUnauthorized = 401
CodeErrUnSafety = 402
CodeErrForbidden = 403
CodeErrNotFound = 404
CodePasswordExpired = 405
CodeAuth = 406 CodeAuth = 406
CodeGlobalLoading = 407 CodeGlobalLoading = 407
CodeErrIP = 408
CodeErrDomain = 409
CodeErrInternalServer = 500 CodeErrInternalServer = 500
CodeErrHeader = 406
CodeErrIP = 310
CodeErrDomain = 311
CodeErrEntrance = 312
CodePasswordExpired = 313
CodeErrXpack = 410 CodeErrXpack = 410
) )

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/i18n" "github.com/1Panel-dev/1Panel/backend/i18n"
"github.com/1Panel-dev/1Panel/backend/middleware" "github.com/1Panel-dev/1Panel/backend/middleware"
@ -64,8 +63,6 @@ func Routers() *gin.Engine {
PublicGroup.GET("/health", func(c *gin.Context) { PublicGroup.GET("/health", func(c *gin.Context) {
c.JSON(200, "ok") c.JSON(200, "ok")
}) })
baseApi := v1.ApiGroupApp.BaseApi
PublicGroup.GET("/api/v1/respagecode", baseApi.GetResponsePage)
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression)) PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
setWebStatic(PublicGroup) setWebStatic(PublicGroup)
} }

View File

@ -1,7 +1,6 @@
package middleware package middleware
import ( import (
"errors"
"strings" "strings"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
@ -29,7 +28,7 @@ func BindDomain() gin.HandlerFunc {
} }
if domains != status.Value { if domains != status.Value {
helper.ErrorWithDetail(c, constant.CodeErrDomain, constant.ErrTypeInternalServer, errors.New("domain not allowed")) helper.ErrResponse(c, LoadErrCode("err-domain"))
return return
} }
c.Next() c.Next()

View File

@ -0,0 +1,42 @@
package middleware
import (
"net/http"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/constant"
)
func LoadErrCode(errInfo string) int {
settingRepo := repo.NewISettingRepo()
codeVal, err := settingRepo.Get(settingRepo.WithByKey("NoAuthSetting"))
if err != nil {
return 500
}
switch codeVal.Value {
case "400":
return http.StatusBadRequest
case "401":
return http.StatusUnauthorized
case "403":
return http.StatusForbidden
case "404":
return http.StatusFound
case "408":
return http.StatusRequestTimeout
case "416":
return http.StatusRequestedRangeNotSatisfiable
default:
if errInfo == "err-ip" {
return constant.CodeErrIP
}
if errInfo == "err-domain" {
return constant.CodeErrDomain
}
if errInfo == "err-entrance" {
return constant.CodeErrEntrance
}
return http.StatusOK
}
}

View File

@ -1,7 +1,6 @@
package middleware package middleware
import ( import (
"errors"
"net" "net"
"strings" "strings"
@ -35,7 +34,7 @@ func WhiteAllow() gin.HandlerFunc {
return return
} }
} }
helper.ErrorWithDetail(c, constant.CodeErrIP, constant.ErrTypeInternalServer, errors.New("IP address not allowed")) helper.ErrResponse(c, LoadErrCode("err-ip"))
} }
} }

View File

@ -33,11 +33,11 @@ func PasswordExpired() gin.HandlerFunc {
loc, _ := time.LoadLocation(common.LoadTimeZone()) loc, _ := time.LoadLocation(common.LoadTimeZone())
expiredTime, err := time.ParseInLocation("2006-01-02 15:04:05", extime.Value, loc) expiredTime, err := time.ParseInLocation("2006-01-02 15:04:05", extime.Value, loc)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodePasswordExpired, constant.ErrTypePasswordExpired, err) helper.ErrResponse(c, constant.CodePasswordExpired)
return return
} }
if time.Now().After(expiredTime) { if time.Now().After(expiredTime) {
helper.ErrorWithDetail(c, constant.CodePasswordExpired, constant.ErrTypePasswordExpired, nil) helper.ErrResponse(c, constant.CodePasswordExpired)
return return
} }
c.Next() c.Next()

View File

@ -41,6 +41,7 @@ class RequestHttp {
this.service.interceptors.response.use( this.service.interceptors.response.use(
(response: AxiosResponse) => { (response: AxiosResponse) => {
globalStore.errStatus = '';
const { data } = response; const { data } = response;
if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) { if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) {
globalStore.setLogStatus(false); globalStore.setLogStatus(false);
@ -50,26 +51,6 @@ class RequestHttp {
}); });
return Promise.reject(data); return Promise.reject(data);
} }
if (data.code == ResultEnum.EXPIRED) {
router.push({ name: 'Expired' });
return data;
}
if (data.code == ResultEnum.ERRIP) {
globalStore.setLogStatus(false);
router.push({
name: 'entrance',
params: { code: 'err-ip' },
});
return Promise.reject(data);
}
if (data.code == ResultEnum.ERRDOMAIN) {
globalStore.setLogStatus(false);
router.push({
name: 'entrance',
params: { code: 'err-domain' },
});
return Promise.reject(data);
}
if (data.code == ResultEnum.ERRXPACK) { if (data.code == ResultEnum.ERRXPACK) {
globalStore.isProductPro = false; globalStore.isProductPro = false;
window.location.reload(); window.location.reload();
@ -94,13 +75,50 @@ class RequestHttp {
return data; return data;
}, },
async (error: AxiosError) => { async (error: AxiosError) => {
globalStore.errStatus = '';
const { response } = error; const { response } = error;
if (error.message.indexOf('timeout') !== -1) MsgError(''); if (error.message.indexOf('timeout') !== -1) MsgError('');
if (response) { if (response) {
checkStatus( switch (response.status) {
response.status, case 310:
response.data && response.data['message'] ? response.data['message'] : '', globalStore.errStatus = 'err-ip';
); router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
return;
case 311:
globalStore.errStatus = 'err-domain';
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
return;
case 312:
globalStore.errStatus = 'err-entrance';
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
return;
case 313:
router.push({ name: 'Expired' });
return;
case 500:
case 400:
case 407:
checkStatus(
response.status,
response.data && response.data['message'] ? response.data['message'] : '',
);
return;
default:
globalStore.errStatus = 'code-' + response.status;
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
}
} }
if (!window.navigator.onLine) router.replace({ path: '/500' }); if (!window.navigator.onLine) router.replace({ path: '/500' });
return Promise.reject(error); return Promise.reject(error);

View File

@ -21,10 +21,6 @@ export const checkIsSafety = (code: string) => {
return http.get<string>(`/auth/issafety?code=${code}`); return http.get<string>(`/auth/issafety?code=${code}`);
}; };
export const getResponsePage = () => {
return http.get<string>(`/respagecode`);
};
export const checkIsDemo = () => { export const checkIsDemo = () => {
return http.get<boolean>('/auth/demo'); return http.get<boolean>('/auth/demo');
}; };

View File

@ -1,10 +1,16 @@
<template> <template>
<div class="not-container"> <div>
<img src="@/assets/images/error.svg" class="not-img" :alt="props.code" /> <body>
<div class="not-detail"> <div>
<h2>{{ props.code }}</h2> <el-row type="flex" justify="center">
<h4>{{ $t('setting.' + 'error' + props.code) }}</h4> <h1>{{ loadErrInfo() }}</h1>
</div> </el-row>
</div>
<hr />
<div>
<el-row type="flex" justify="center"><span>nginx</span></el-row>
</div>
</body>
</div> </div>
</template> </template>
@ -12,37 +18,24 @@
const props = defineProps({ const props = defineProps({
code: String, code: String,
}); });
const loadErrInfo = () => {
switch (props.code) {
case '401':
return '401 Unauthorized';
case '403':
return '403 Forbidden';
case '404':
return '403 Not Found';
case '408':
return '408 Request Timeout';
case '416':
return '408 Requested Not Satisfiable';
}
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.not-container { .container {
display: flex; margin-left: 40%;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
.not-img {
margin-top: 300px;
}
.not-detail {
margin-top: 300px;
display: flex;
flex-direction: column;
h2,
h4 {
padding: 0;
margin: 0;
}
h2 {
font-size: 60px;
color: #434e59;
}
h4 {
margin: 30px 0 20px;
font-size: 19px;
font-weight: normal;
color: #848587;
}
}
} }
</style> </style>

View File

@ -1,14 +1,15 @@
export enum ResultEnum { export enum ResultEnum {
SUCCESS = 200, SUCCESS = 200,
ERRIP = 310,
ERRDOMAIN = 311,
UNSAFETY = 312,
EXPIRED = 313,
ERROR = 500, ERROR = 500,
OVERDUE = 401, OVERDUE = 401,
UNSAFETY = 402,
FORBIDDEN = 403, FORBIDDEN = 403,
EXPIRED = 405,
ERRAUTH = 406, ERRAUTH = 406,
ERRGLOBALLOADDING = 407, ERRGLOBALLOADDING = 407,
ERRIP = 408,
ERRDOMAIN = 409,
ERRXPACK = 410, ERRXPACK = 410,
TIMEOUT = 20000, TIMEOUT = 20000,
TYPE = 'success', TYPE = 'success',

View File

@ -34,6 +34,8 @@ export interface GlobalState {
isProductPro: boolean; isProductPro: boolean;
productProExpires: number; productProExpires: number;
errStatus: string;
} }
export interface MenuState { export interface MenuState {

View File

@ -38,6 +38,8 @@ const GlobalStore = defineStore({
isProductPro: false, isProductPro: false,
productProExpires: 0, productProExpires: 0,
errStatus: '',
}), }),
getters: { getters: {
isDarkTheme: (state) => state.themeConfig.theme === 'dark' || state.themeConfig.theme === 'dark-gold', isDarkTheme: (state) => state.themeConfig.theme === 'dark' || state.themeConfig.theme === 'dark-gold',

View File

@ -18,22 +18,20 @@
</div> </div>
<div v-else> <div v-else>
<div v-if="!pageCode || pageCode === '200'"> <div v-if="errStatus === 'err-unsafe'">
<div v-if="errStatus === 'err-unsafe'"> <UnSafe />
<UnSafe />
</div>
<div v-if="errStatus === 'err-ip'">
<ErrIP />
</div>
<div v-if="errStatus === 'err-domain'">
<ErrDomain />
</div>
<div v-if="errStatus === 'not-found'">
<ErrFound />
</div>
</div> </div>
<div v-else> <div v-if="errStatus === 'err-ip'">
<ErrCode :code="pageCode" /> <ErrIP />
</div>
<div v-if="errStatus === 'err-domain'">
<ErrDomain />
</div>
<div v-if="errStatus.indexOf('code-') !== -1">
<ErrCode :code="errStatus.replaceAll('code-', '')" />
</div>
<div v-if="errStatus === 'not-found'">
<ErrFound />
</div> </div>
</div> </div>
</div> </div>
@ -41,7 +39,7 @@
</template> </template>
<script setup lang="ts" name="login"> <script setup lang="ts" name="login">
import { checkIsSafety, getResponsePage } from '@/api/modules/auth'; import { checkIsSafety } from '@/api/modules/auth';
import LoginForm from '../components/login-form.vue'; import LoginForm from '../components/login-form.vue';
import UnSafe from '@/components/error-message/unsafe.vue'; import UnSafe from '@/components/error-message/unsafe.vue';
import ErrIP from '@/components/error-message/err_ip.vue'; import ErrIP from '@/components/error-message/err_ip.vue';
@ -54,8 +52,7 @@ import { getXpackSetting, initFavicon } from '@/utils/xpack';
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const screenWidth = ref(null); const screenWidth = ref(null);
const errStatus = ref(); const errStatus = ref('');
const pageCode = ref('');
const loading = ref(); const loading = ref();
const mySafetyCode = defineProps({ const mySafetyCode = defineProps({
@ -66,52 +63,35 @@ const mySafetyCode = defineProps({
}); });
const getStatus = async () => { const getStatus = async () => {
let info = globalStore.errStatus;
if (info?.startsWith('err-') || info?.startsWith('code-')) {
errStatus.value = info;
return;
}
let code = mySafetyCode.code; let code = mySafetyCode.code;
globalStore.entrance = code;
loading.value = true; loading.value = true;
await getResponsePage() await checkIsSafety(code)
.then(async (res) => { .then(() => {
pageCode.value = res.data;
if (code === 'err-ip' || code === 'err-domain') {
errStatus.value = code;
loading.value = false;
return;
}
await checkIsSafety(code)
.then((safeRes) => {
if (safeRes.data === 'unpass') {
loading.value = false;
errStatus.value = 'err-unsafe';
return;
}
if (safeRes.data === 'disable') {
if (code !== '') {
errStatus.value = 'not-found';
loading.value = false;
return;
}
}
globalStore.entrance = code;
errStatus.value = '';
loadDataFromXDB();
})
.catch((errRes) => {
pageCode.value = pageCode.value || '200';
loading.value = false;
if (errRes?.code === 408) {
errStatus.value = 'err-ip';
return;
}
if (errRes?.code === 409) {
errStatus.value = 'err-domain';
return;
}
errStatus.value = 'err-unsafe';
});
})
.catch(() => {
pageCode.value = '200';
errStatus.value = 'err-found';
loading.value = false; loading.value = false;
errStatus.value = '';
loadDataFromXDB();
})
.catch((err) => {
loading.value = false;
switch (err.response.status) {
case 310:
errStatus.value = 'err-ip';
return;
case 311:
errStatus.value = 'err-domain';
return;
case 312:
errStatus.value = 'err-entrance';
return;
default:
errStatus.value = 'code-' + err.response.status;
}
}); });
}; };