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

登录API中window.sessionStorage.accessToken无法更新及JWT过期报错问题

解决AngularJS登录中sessionStorage无法更新及JWT过期错误的问题

咱们先拆解你的核心问题:从错误信息来看,JWT令牌过期导致的后端异常,直接让前端更新sessionStorage的代码根本没机会执行——因为请求直接进入了errorCallback分支,而非successCallback里的200处理逻辑。下面一步步来解决:

1. 先理清错误链路

你给出的错误信息里藏着一个矛盾:后端实际是因为JWT过期抛出了401 Unauthorized,但最终返回给前端的是500 Internal Server Error。这说明后端在处理过期token时,没有正确捕获异常并返回标准状态码,而是抛出了未处理的错误。

前端侧:修正请求逻辑与错误处理

先调整你的登录代码,完善逻辑分支,同时规范sessionStorage的使用:

// 记得在控制器里注入$location、$timeout、$rootScope这些服务
$scope.onSelect = function(admin_email, admin_password) {
    console.log(admin_email, admin_password);
    console.log("User Name: ", $scope.admin_email, "Password : ", $scope.admin_password);
    
    var mydata = {
        admin_email: $scope.admin_email,
        admin_password: $scope.admin_password
    };

    $http({
        async: true,
        method: 'POST',
        url: 'http://localhost:3000/api/v1/users/login',
        data: mydata
    }).then(function successCallback(response) {
        // 同时判断HTTP状态和业务状态,避免仅靠200判断成功
        if (response.status === 200 && !response.data.error) {
            console.log({response});
            $rootScope.isLogged = true;
            
            // 同步设置sessionStorage,不需要setTimeout
            window.sessionStorage.setItem('accessToken', response.data.token);
            
            $("#loginModal").modal("hide");
            // 用AngularJS的$location服务替代window.location,更符合路由机制
            $timeout(function() {
                $location.path('/dashboard');
            }, 1000);
        } else {
            alert('Username or password is incorrect');
        }
    }, function errorCallback(response) {
        // 根据错误类型给出精准提示
        let errorMsg = "Login failed. ";
        if (response.data?.name === 'UnauthorizedError' && response.data?.message === 'jwt expired') {
            errorMsg += "Your session has expired, please login again.";
        } else if (response.status === 401) {
            errorMsg += "Invalid username or password.";
        } else {
            errorMsg += "Check the console for details.";
        }
        alert(errorMsg);
        console.error('Login error details:', response);
    });
};

关键修改点:

  • 去掉setTimeout包裹sessionStorage的代码:设置sessionStorage是同步操作,延迟反而会导致执行时机不可控;同时推荐用setItem方法,比直接赋值更规范兼容。
  • 替换window.location为$location:这是AngularJS路由的标准用法,避免直接操作原生window导致的路由状态不一致。
  • 完善错误提示:根据后端返回的错误类型,给用户明确的反馈,而非笼统的错误信息。

2. 后端侧:修复JWT过期的响应逻辑

从错误信息来看,后端在处理过期token时抛出了TokenExpiredError但未正确捕获,导致返回500错误而非标准的401。你需要在后端的JWT验证中间件或登录接口里:

  • 主动捕获TokenExpiredError异常
  • 返回标准的401 Unauthorized响应,同时带上清晰的错误信息(比如{"error": true, "message": "jwt expired"})

这样前端才能正确识别错误类型,进入对应的处理分支,避免混淆。

3. 为什么之前sessionStorage无法更新?

因为你的请求因JWT过期(或后端500错误)直接进入了errorCallback,而设置sessionStorage的代码只在successCallback的200分支里,所以这段代码根本没被执行。解决后端错误响应和前端逻辑后,登录成功时sessionStorage就能正常设置了。

额外小建议

  • 尽量避免在AngularJS控制器里直接操作DOM(比如$("#loginModal").modal("hide")),推荐用AngularJS UI Bootstrap的模态框组件,通过控制器变量控制显示/隐藏,更符合MVVM模式。
  • 把登录逻辑封装到AngularJS服务(Service)里,而非直接写在控制器中,这样代码更易维护和复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:42:51