首页 文章

从https切换到http时,spring-boot用户会话在登录后未添加到上下文中

提问于
浏览
1

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

方案如下:

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

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

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

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

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

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

Edit: this does not happen when I restart the spring-boot application or when a I open a new browser session (chrome person). Seems like it happens only after logging out

我将此跟踪到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重定向到 login

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

onApplicationEvent - 为用户进行身份验证的会话:admin,sessionId:80CDEA048679E189485FE0F4597BE2E8(TestFilter.java:34)访问的URL:https:// localhost:8443 / auth / login;当前用户:Annonymous(TestFilter.java:34)访问的URL:https:// localhost:8443 / auth / login-secure;当前用户:Annonymous(TestFilter.java:34)访问的URL:https:// localhost:8443 / auth / login-strings;当前用户:Annonymous

  • 用户被重定向到通过HTTP登录,通过HTTPS重定向到安全登录

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

  • defaultEntry 现在直接通过HTTP加载(不再首先尝试通过HTTPS)并加载主页

onApplicationEvent - 为用户进行身份验证的会话:admin,sessionId:933F361668CFF01EBCC0DF88763D4DF4(TestFilter.java:34)访问的URL:http:// localhost:8000 / defaultEntry;当前用户:CGSUserDetailsImpl {firstName ='admin',lastName ='admin',email ='admin @ mycompany.com'}

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

我怎样才能让它第一次正确地重定向到家?

1 回答

  • 0

    好的,我修好了 . 就我而言,问题是由注销表单引起的 .

    @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>
    

    我删除了这个.jsp并将注销映射更改为:

    @RequestMapping(value = "/auth/logout-success", method = RequestMethod.GET)
    public String logoutSuccess() {
        return "redirect:/defaultEntry";
    }
    

相关问题