Merge pull request #20 from aaronjmars/security/open-redirect-guard
fix(security): block open redirect in login redirect target
This commit is contained in:
@@ -15,6 +15,16 @@ type LoginFormValues = {
|
||||
confirmPassword?: string;
|
||||
};
|
||||
|
||||
// 仅放行站内相对路径,拦截开放重定向。浏览器会忽略 URL 中的 Tab/换行/回车,并把
|
||||
// //host 或 /\host 解析为协议相对的跨站地址,因此先剥离控制字符,再拒绝 // 与 /\ 前缀。
|
||||
function safeRedirect(value: string | null): string {
|
||||
const cleaned = (value ?? "").replace(/[\t\n\r]/g, "");
|
||||
if (!cleaned.startsWith("/") || cleaned.startsWith("//") || cleaned.startsWith("/\\")) {
|
||||
return "/";
|
||||
}
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
@@ -34,7 +44,7 @@ function LoginContent() {
|
||||
const linuxDoEnabled = useConfigStore((state) => state.publicSettings?.auth?.linuxDo?.enabled === true);
|
||||
const allowRegister = useConfigStore((state) => state.publicSettings?.auth?.allowRegister !== false);
|
||||
const [mode, setMode] = useState<"login" | "register">("login");
|
||||
const redirect = searchParams.get("redirect") || "/";
|
||||
const redirect = safeRedirect(searchParams.get("redirect"));
|
||||
|
||||
useEffect(() => {
|
||||
const token = searchParams.get("token");
|
||||
@@ -44,7 +54,7 @@ function LoginContent() {
|
||||
void fetchCurrentUser(token).then((user) => {
|
||||
setSession(token, user);
|
||||
message.success("登录成功");
|
||||
router.replace(redirect.startsWith("/") ? redirect : "/");
|
||||
router.replace(redirect);
|
||||
router.refresh();
|
||||
});
|
||||
}, [message, redirect, router, searchParams, setSession]);
|
||||
@@ -66,7 +76,7 @@ function LoginContent() {
|
||||
const action = mode === "register" ? register : login;
|
||||
const user = await action({ username: values.username, password: values.password });
|
||||
message.success(mode === "register" ? "注册成功" : "登录成功");
|
||||
router.replace(redirect.startsWith("/") ? redirect : "/");
|
||||
router.replace(redirect);
|
||||
router.refresh();
|
||||
if (user.role !== "admin") router.replace("/");
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user