Authentication 从https切换到http时,登录后未将spring引导用户会话添加到上下文

Authentication 从https切换到http时,登录后未将spring引导用户会话添加到上下文,authentication,redirect,spring-security,spring-boot,spring-session,Authentication,Redirect,Spring Security,Spring Boot,Spring Session,我有一个spring boot 1.3.5.RELEASE和spring security 4.1.0.RELEASE应用程序,用户在第一次输入用户名和密码后会被重定向到登录页面。第二次他们输入用户名和密码时,它工作正常 情况如下: 用户被重定向到登录页面(使用HTTPS) 用户输入用户名和密码,然后按enter键 用户再次被重定向到登录页面,就好像他没有输入用户名和密码一样 用户再次输入用户名和密码,然后按enter键 用户被重定向到主页(HTTP) 每次用户尝试登录时都会发生这种情况 编辑:

我有一个spring boot 1.3.5.RELEASE和spring security 4.1.0.RELEASE应用程序,用户在第一次输入用户名和密码后会被重定向到登录页面。第二次他们输入用户名和密码时,它工作正常

情况如下:

  • 用户被重定向到登录页面(使用HTTPS)

  • 用户输入用户名和密码,然后按enter键

  • 用户再次被重定向到登录页面,就好像他没有输入用户名和密码一样

  • 用户再次输入用户名和密码,然后按enter键

  • 用户被重定向到主页(HTTP)

  • 每次用户尝试登录时都会发生这种情况

    编辑:重新启动spring boot应用程序或打开新浏览器会话(chrome person)时不会发生这种情况。似乎只有在注销后才会发生这种情况

    我追踪到spring的用户会话固定,但不知道如何解决这个问题

    我的配置看起来如何:

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .headers().disable()
            .csrf().disable()
            .formLogin()
                .loginPage("/auth/login")
                .loginProcessingUrl("/auth/login")
                .failureUrl("/auth/login-secure?loginFailed=true")
                .defaultSuccessUrl("/defaultEntry")
                .usernameParameter("username")
                .passwordParameter("password")
            .and()
            .logout()
                .logoutUrl("/auth/logout")
                .logoutSuccessUrl("/auth/logout-success")
            .deleteCookies("jsessionid", "JSESSIONID")
            .and()
            .sessionManagement().sessionFixation().none()
            .and()
            .anonymous().principal(ANONYMOUS_USER)
    
            .and()
            .authorizeRequests()
                .antMatchers("/websocket/**").authenticated()
                .antMatchers("/auth/login", "/auth/login-secure", "/auth/login-oauth2").permitAll()
                .antMatchers("/auth/external-logout").authenticated()
                .antMatchers("/index.jsp").permitAll()
                .antMatchers("/defaultEntry").authenticated()
                .antMatchers("/admin/**/*").hasRole("T2K_ADMIN")
                .antMatchers("/client/**/*").authenticated();
    
        // we set the redirect port for https for dev environment. Production environment has the connectors configured in Tomcat's server.xml
        if (Arrays.asList(environment.getActiveProfiles()).contains(SpringProfiles.DEVELOPMENT)) {
            http.portMapper()
                    .http(Integer.parseInt(environment.getProperty("server.port")))
                    .mapsTo(Integer.parseInt(environment.getProperty("server.https.port")));
        }
    
        http.requiresChannel()
                .antMatchers("/auth/**").requiresSecure()
                .anyRequest().requiresInsecure();
    }
    
    控制器:

    @Controller
    public class HomeController {
    
        @Autowired
        private CGSUserDetails currentUser;
    
        @Autowired
        private Authentication authentication;
    
        @RequestMapping(value = "/auth/login", method = RequestMethod.GET)
        public String login() {
            return "redirect:login-secure";
        }
    
        @RequestMapping(value = "/auth/login-secure", method = RequestMethod.GET)
        public String loginSecure() {
            if (authentication.isAuthenticated() && !ANONYMOUS_USER.equals(authentication.getName())) {
                return "redirect:/defaultEntry";
            } else {
                return "auth/login"; // get /auth/login.jsp
            }
        }
    
        @RequestMapping(value = {"/home"}, method = RequestMethod.GET)
        public String openHomePage() throws Exception {
            if (authentication.isAuthenticated() && !ANONYMOUS_USER.equals(authentication.getName())) {
                return "index";
            } else {
                return "redirect:/defaultEntry";
            }
        }
    
        @RequestMapping(value = "/defaultEntry", method = RequestMethod.GET)
        public String defaultEntry() {
            if (authentication.isAuthenticated() && !ANONYMOUS_USER.equals(authentication.getName())) {
                return "redirect:/home";
            } else {
                return "redirect:login";
            }
        }
    }
    
    用户和身份验证bean:

    @Bean(name = "userDetails")
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public UserDetails userDetails() {
        return AuthenticationHolder.getUserDetails();
    }
    
    @Bean(name = "authentication")
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Authentication authentication() {
        return AuthenticationHolder.getAuthentication();
    }
    
    调试期间我发现:

  • 加载页面时,浏览器通过HTTPS重定向到
    登录

  • 用户输入用户名和密码并按enter键后,浏览器尝试通过HTTPS加载
    defaultEntry
    ,然后通过HTTP重定向到
    defaultEntry
    。 我放置了一个过滤器和一个应用程序侦听器来跟踪正在发生的事情,我看到了以下内容 登录时按enter键后:

  • onApplicationEvent-已为用户管理员验证会话,会话ID:80CDEA048679E189485FE0F4597BE2E8

    (TestFilter.java:34)访问的URL:;当前用户:Annonymous

    (TestFilter.java:34)访问的URL:;当前用户:Annonymous

    (TestFilter.java:34)访问的URL:;当前用户:Annonymous

  • 用户被重定向到通过HTTP登录,从而重定向到通过HTTPS的安全登录
  • 用户再次输入用户名和密码,然后按enter键
  • defaultEntry
    现在直接通过HTTP加载(不再通过HTTPS进行首次尝试),并加载主页
  • onApplicationEvent-已为用户管理员验证会话,会话ID:933F361668CFF01EBCC0DF88763D4DF4

    (TestFilter.java:34)访问的URL:;当前用户:cgsUserDetailSimp{firstName='admin',lastName='admin',email='admin@mycompany.com“}

    我还尝试更改sessionFixation模式和范围,但在其他配置中,用户和授权不再自动连接

    如何使它第一次正确重定向到主页?

    好的,我已修复。 在我的例子中,问题是由注销表单引起的

    @RequestMapping(value = "/auth/logout-success", method = RequestMethod.GET)
    public String logoutSuccess() {
        return "auth/logout-success";
    }
    
    这是在加载下面的.jsp

    <head>
        <title>Logout</title>
    </head>
    <body>
        <script type="text/javascript">
            window.location = "login";
        </script>
    </body>
    
    好的,我修好了。 在我的例子中,问题是由注销表单引起的

    @RequestMapping(value = "/auth/logout-success", method = RequestMethod.GET)
    public String logoutSuccess() {
        return "auth/logout-success";
    }
    
    这是在加载下面的.jsp

    <head>
        <title>Logout</title>
    </head>
    <body>
        <script type="text/javascript">
            window.location = "login";
        </script>
    </body>