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

如何在Spring Security+AngularJS中保持登录?刷新登出问题求解

解决浏览器刷新后自动登出问题的详细思路

我来帮你一步步排查这个JWT+AngularJS项目里的刷新登出问题,这个场景其实挺常见的,咱们从几个核心关键点入手:

一、先调整请求头设置的时机,别在控制器里搞!

你现在在home.js里设置$http.defaults.headers.common['Authorization']的时机太晚了——刷新页面后,AngularJS的模块初始化是有顺序的,控制器代码(比如home.js里的逻辑)往往是在路由跳转完成后才执行,这时候第一个请求早就发出去了,根本没带上Authorization头,后端自然判定你未授权,直接触发登出。

正确的姿势是用HTTP拦截器,每次请求前自动从$sessionStorage里拿token并塞进请求头,不管页面怎么刷新都能生效:

// 先创建一个拦截器工厂
angular.module('yourApp').factory('authInterceptor', ['$sessionStorage', function($sessionStorage) {
    return {
        request: function(config) {
            // 检查sessionStorage里有没有有效token,记得加Bearer前缀(大部分JWT后端都要求这个格式)
            if ($sessionStorage.loginSession) {
                config.headers['Authorization'] = 'Bearer ' + $sessionStorage.loginSession;
            }
            return config;
        }
    };
}]);

// 然后在模块配置里注册这个拦截器
angular.module('yourApp').config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
}]);

这样不管是页面刷新还是正常跳转,所有请求都会自动带上token,不会因为初始化顺序掉链子。

二、检查JWT本身和后端配置是否匹配

  1. 先确认token没过期:刷新页面后,打开浏览器开发者工具→Application→Session Storage,找到loginSession的值,然后用控制台的atob()解析token的payload部分(比如atob('token的中间段')),看看exp字段对应的时间是不是已经过期了。如果token过期,后端肯定会拒绝请求,这时候得加个token刷新的逻辑。
  2. 后端是否正确识别Authorization头:看看Spring Security的JWT过滤器配置,是不是正确读取了Authorization头里的token,尤其是有没有处理Bearer 前缀。比如后端过滤器里应该有类似这样的代码:
// Spring Security JWT过滤器示例片段
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        // 必须检查头是否存在,且以Bearer开头
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7); // 去掉Bearer前缀拿纯token
            // 接下来解析token、验证有效性、把认证信息存入SecurityContext
        }
        filterChain.doFilter(request, response);
    }
}

如果后端没处理前缀,或者头的名称写错了,哪怕前端传了token,后端也认不出来,照样会返回未授权。

三、给路由加个"门卫",刷新时先验证身份

刷新页面后,AngularJS的路由会重新加载,这时候得在路由跳转前先确认token是否有效,别直接跳登录页:
给需要授权的路由加个resolve属性,在页面加载前先发起一个验证请求(比如后端的/api/user/me接口,用来返回当前用户信息),确认token有效再加载页面:

angular.module('yourApp').config(['$routeProvider', function($routeProvider) {
    $routeProvider
        .when('/home', {
            templateUrl: 'home.html',
            controller: 'HomeController',
            resolve: {
                auth: ['$http', '$sessionStorage', '$location', function($http, $sessionStorage, $location) {
                    // 先检查sessionStorage里有没有token
                    if (!$sessionStorage.loginSession) {
                        $location.path('/login');
                        return;
                    }
                    // 发起验证请求,确认token能被后端识别
                    return $http.get('/api/user/me')
                        .catch(function() {
                            // 验证失败,清掉无效token跳登录
                            delete $sessionStorage.loginSession;
                            $location.path('/login');
                        });
                }]
            }
        });
}]);

这样刷新页面时,路由会先做身份验证,有效就继续加载,无效才跳登录,避免误登出。

四、排查sessionStorage的存储问题

有时候可能是$sessionStorage.loginSession在刷新后没读取到:

  1. 刷新前后都在控制台敲console.log($sessionStorage.loginSession),看看值是否存在。如果刷新后为空,说明登录时没把token正确存进sessionStorage,检查登录控制器里的代码:
$scope.login = function() {
    $http.post('/api/login', {username: $scope.username, password: $scope.password})
        .then(function(response) {
            // 确保这里存的是后端返回的有效JWT token
            $sessionStorage.loginSession = response.data.token;
        });
};
  1. 还要确认你的模块已经注入了ngStorage——$sessionStorage是这个第三方模块提供的,没注入的话它就是undefined,自然读不到token:
// 根模块依赖里必须包含ngStorage
angular.module('yourApp', ['ngRoute', 'ngStorage']);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:37:47