You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextAuth Credentials Provider登录失败异常重定向问题排查

问题分析与解决方案

核心问题

你的配置存在两处关键问题:

  1. 当authorize返回null时,NextAuth默认会触发错误跳转至/api/auth/error,且此时signIn回调不会被执行,导致你写的跳转逻辑完全无效。
  2. 登录页已设置redirect:false,但你没有利用signIn返回的结果手动处理错误流程,而是依赖NextAuth的自动跳转机制。

修复步骤

1. 调整[...nextauth].js配置

移除无效的signIn回调,在authorize中明确抛出错误(或返回null),让错误信息能传递到登录页:

import { authenticate } from "api/login";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({
  session: {
    strategy: 'jwt'
  },
  providers: [
    CredentialsProvider({
      id: 'credentials',
      name: 'Credentials',
      credentials: {
        username: { type: 'text', label: 'Username'},
        password: { type: 'password', label: 'Password' }
      },
      async authorize(credentials, req) {
        const res = await authenticate(credentials);

        if(res.status !== 200) {
          // 抛出错误,让signIn返回结果携带错误信息
          throw new Error('Login failed');
        }

        return res.user;
      }
    })
  ],
  pages: {
    signIn: '/login'  
  }
});

2. 修改登录页login.js的错误处理逻辑

利用redirect:false返回的结果,手动控制跳转和错误提示:

import { useState, useEffect } from 'react';
import { signIn, useRouter } from 'next-auth/react';

import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';

export default function Login() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const router = useRouter();
  const { status } = router.query;

  // 从URL参数读取登录状态,显示错误提示
  useEffect(() => {
    if (status === 'Failed') {
      // 这里可以添加错误提示UI,比如弹窗或文字提示
      console.log('登录失败,请检查用户名或密码');
    }
  }, [status]);

  const onSubmit = async () => {
    const result = await signIn('credentials', {
      username: username,
      password: password,
      redirect: false,
    });

    if (result.ok) {
      // 登录成功,跳转到首页
      router.push('/');
    } else {
      // 登录失败,修改URL添加状态参数
      router.push('/login?status=Failed');
      // 也可以直接用state存储错误信息,无需修改URL
      // setLoginError('用户名或密码错误');
    }
  };

  return (
    <Container>
      <Row>
        <Col lg={6} className="offset-lg-3">
          {/* 错误提示区域 */}
          {status === 'Failed' && (
            <p style={{ color: 'red', marginBottom: '1rem' }}>登录失败,请检查用户名或密码</p>
          )}
          <Form>
            <Row>
              <Col>
                <Form.Group controlId="loginUsername">
                  <Form.Label>Username</Form.Label>
                  <Form.Control 
                    type="text"
                    onChange={(e) => setUsername(e.target.value)}
                    value={username} />
                </Form.Group>
              </Col>
            </Row>
            <Row>
              <Col>
                <Form.Group controlId="loginPassword">
                  <Form.Label>Password</Form.Label>
                  <Form.Control 
                    type="password"
                    onChange={(e) => setPassword(e.target.value)}
                    value={password} />
                </Form.Group>
              </Col>
            </Row>
            <Row className="pt-3">
              <Col lg={4}>
                <Button onClick={onSubmit}>Login</Button>
              </Col>
            </Row>
          </Form>
        </Col>
      </Row>
    </Container>
  )
}

3. 额外优化建议

  • 将密码输入框的type改为password,避免明文显示。
  • 可以用组件内状态存储错误信息,不需要修改URL,用户体验更流畅。

内容的提问来源于stack exchange,提问作者ttse76

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:31:02