From 900cafd8fa7dc050f3ca1f2845c01aec065cb80c Mon Sep 17 00:00:00 2001 From: Mmx233 Date: Mon, 30 Oct 2023 18:07:52 +0800 Subject: [PATCH] =?UTF-8?q?improve:=20=E4=B8=8D=E8=87=AA=E5=8A=A8=E9=94=80?= =?UTF-8?q?=E6=AF=81=20u2f=20token=EF=BC=8C5mins=20=E5=86=85=E8=AE=B0?= =?UTF-8?q?=E4=BD=8F=E6=A0=A1=E9=AA=8C=E4=BB=A4=E7=89=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/pkg/jwt/jwt.go | 3 +- internal/pkg/tokenStore/tokenStore.go | 2 +- web/src/components/user/U2fDialog.tsx | 110 +++++++++++++++++--------- 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/internal/pkg/jwt/jwt.go b/internal/pkg/jwt/jwt.go index a74e165d..3662ded9 100644 --- a/internal/pkg/jwt/jwt.go +++ b/internal/pkg/jwt/jwt.go @@ -141,14 +141,13 @@ func GenerateU2fToken(uid uint, ip string) (string, *U2fToken, error) { return token, tokenClaims, err } -// ParseU2fToken 自动销毁 func ParseU2fToken(token, ip string) (bool, error) { claims, valid, err := ParseToken("U2F", token, &U2fToken{}) if err != nil || !valid || claims.IP != ip { return false, err } - err = redis.NewU2F(claims.UID).NewStorePoint(claims.ID).GetAndDestroy(context.Background(), claims.IssuedAt.Time, nil) + err = redis.NewU2F(claims.UID).NewStorePoint(claims.ID).Get(context.Background(), claims.IssuedAt.Time, nil) if err != nil { if err == redis.Nil { err = nil diff --git a/internal/pkg/tokenStore/tokenStore.go b/internal/pkg/tokenStore/tokenStore.go index 0c284d4f..6329a91a 100644 --- a/internal/pkg/tokenStore/tokenStore.go +++ b/internal/pkg/tokenStore/tokenStore.go @@ -77,7 +77,7 @@ func (a Point) GetAndDestroy(ctx context.Context, iat time.Time, claims interfac } func (a Point) Get(ctx context.Context, iat time.Time, claims interface{}) error { - value, err := a.s.client.GetDel(ctx, a.key).Bytes() + value, err := a.s.client.Get(ctx, a.key).Bytes() if err != nil { return err } diff --git a/web/src/components/user/U2fDialog.tsx b/web/src/components/user/U2fDialog.tsx index 34d24720..ea79b573 100644 --- a/web/src/components/user/U2fDialog.tsx +++ b/web/src/components/user/U2fDialog.tsx @@ -14,6 +14,8 @@ import { Typography, Stack, TextField, + Alert, + AlertTitle, } from "@mui/material"; import { LoadingButton } from "@mui/lab"; import { @@ -43,6 +45,9 @@ const U2fDialog: FC = () => { }), shallow ); + const u2fToken = useU2fDialog((state) => state.u2f); + + const [tokenAvailable, setTokenAvailable] = useState(false); const [tabValue, setTabValue] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -57,6 +62,16 @@ const U2fDialog: FC = () => { const [mfaCode, setMfaCode] = useState(""); + const isTokenAvailable = () => { + return !!u2fToken && u2fToken.valid_before > Date.now() / 1000; + }; + useInterval( + () => { + if (!isTokenAvailable()) setTokenAvailable(false); + }, + tokenAvailable ? 1000 : null + ); + const onCancel = () => { const states = useU2fDialog.getState(); states.closeDialog(); @@ -64,6 +79,12 @@ const U2fDialog: FC = () => { }; const onSubmit = async (method: string = tabValue) => { + if (tokenAvailable) { + const states = useU2fDialog.getState(); + if (states.resolve) states.resolve(u2fToken!); + states.closeDialog(); + return; + } let data: any; switch (method) { case "phone": @@ -147,7 +168,8 @@ const U2fDialog: FC = () => { if (open) { setMfaCode(""); setSmsCode(""); - if (tabValue === "passkey") onSubmit(); + if (isTokenAvailable()) setTokenAvailable(true); + else if (tabValue === "passkey") onSubmit(); } }, [open]); useEffect(() => { @@ -163,6 +185,9 @@ const U2fDialog: FC = () => { case "phone": return ( + + 每天上限五条,出现异常情况请过会儿再试 + { ); case "passkey": return ( - - - - + + + + ); default: return ( @@ -235,31 +260,42 @@ const U2fDialog: FC = () => { U2F 身份校验 - - {tip ? tip : "你正在进行敏感操作,需要额外的身份校验"} - + {!tip && tokenAvailable ? undefined : ( + + {tip ? tip : "你正在进行敏感操作,需要额外的身份校验"} + + )} - { - setTabValue(value as User.U2F.Methods); - if (value === "passkey") return onSubmit("passkey"); - }} - variant="fullWidth" - sx={{ - mt: 2, - mb: 3, - }} - > - - - - - {renderTabPanel()} + {tokenAvailable ? ( + + 已认证 + 最近 5 分钟已通过验证,无需再次校验。你可以通过刷新提前移除校验状态 + + ) : ( + <> + { + setTabValue(value as User.U2F.Methods); + if (value === "passkey") return onSubmit("passkey"); + }} + variant="fullWidth" + sx={{ + mt: 2, + mb: 3, + }} + > + + + + + {renderTabPanel()} + + )}