【问题标题】:Spring Security - api gateway pattern - bug?Spring Security - api 网关模式 - 错误?
【发布时间】:2017-02-24 08:28:26
【问题描述】:

我们创建了一个模仿 Spring Security - API Gate Pattern 教程 (https://spring.io/guides/tutorials/spring-security-and-angular-js/#_the_api_gateway_pattern_angular_js_and_spring_security_part_iv) 的应用程序。唯一的变化是我们使用的是 MySQL 数据库而不是 Redis。

使用 localhost:8080 作为根,我们有 localhost:8080/login(登录页面)、localhost:8080/ui(jQuery 客户端)和 localhost:8080/api(RESTful Web 服务、业务逻辑等)

我们发现会话处理和转发到各种实体的工作正常。这意味着会话按预期创建,转发按预期发生,等等。有一个例外。如果我登录,然后注销,然后直接转到 localhost:8080/ui,​​它会将我转发到登录页面。您登录,它会将您转发回 localhost:8080/ui,​​但会显示“ACCESS DENIED”!

跟踪数据库和客户端中的会话后,我发现数据库中存在两个会话。一个有权限,一个没有。客户保留一个没有!

还有其他人遇到过这个问题吗?有没有办法绕过这个?

这是我经历的步骤列表、数据库会话跟踪和客户端验证。

session_id principal_name 客户端 -------------------------------------------------- ---------- 1)去本地主机:8080 9229045c-27e0-410a-8711-45c56576d647 - X 2) 登录 2275db1c-fca4-4a2f-be73-e440599499d6 root X 3) 注销 cc917e68-b1c0-46a4-bbe3-6705ccf7a5fa - X 4) 转到 localhost:8080/ui --> 转发到 localhost:8080/login cc917e68-b1c0-46a4-bbe3-6705ccf7a5fa - X 5) 登录 -> 转发到 localhost:8080/ui -> 拒绝访问 90d7931d-b265-42e2-a225-286bcf7d159c - X
d2fae0ac-9cf9-4287-8e38-51f64b0ab28d root

【问题讨论】:

    标签: java spring api spring-security spring-boot


    【解决方案1】:

    最有可能的是,当您直接返回您的 UI 应用程序时,它仍在使用旧会话 ID,而当您登录时,它会再次使用旧会话 ID 将您重定向到 UI。

    也可能是 Tomcat 上的老问题,请查看此线程以了解如何正确清除 cookie:https://straypixels.net/clearing-cookies-in-spring-tomcat/

    基本上,像这样扩展SimpleUrlLogoutSuccessHandler

    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
    throws IOException, ServletException {
        //This search may or may not actually be necessary, you might be able to just
        // create a new cookie with the right name
        for(Cookie cookie : request.getCookies()) {
            if(cookie.getName() == "JSESSIONID") {
                //Clear one cookie
                cookie.setName("");
                cookie.setMaxAge(0);
                cookie.setPath(request.getContextPath());
                response.addCookie(cookie);
                //Clear the other cookie
                Cookie cookieWithSlash = cookie.clone();
                cookieWithSlash.setPath(request.getContextPath() + "/");
                response.addCookie(cookieWithSlash);
            }
        }
        //This is actually a filter; continue along the chain
        super.onLogoutSuccess(request, response, authentication);
    }
    

    【讨论】:

      【解决方案2】:

      好的,经过几个小时后,我们找到了解决似乎不一致的行为的方法。这意味着有时您会登录并且它会保留正确的会话,并且您可以转到 localhost:8080/ui 页面而没有得到 Whitelabel 错误页面......有时您仍然会得到它。

      在网关服务器上...
      1) 添加 RequestMethod.POST

      @Controller
      public class HomeController {
          @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, path = "/")
          public String home() {
              return "redirect:" + RequestMappings.UI;
          }
      }
      

      2) 更改了配置文件,特别是
      a) 添加 .successForwardUrl(“/”)
      b) 添加 .loginProcessingUrl(“/login”)
      c) 添加 .logoutSuccessUrl("/login?logout")

      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http.headers()
              .frameOptions().sameOrigin()
          .and().formLogin()
              .loginPage(RequestMappings.LOGIN)
              .failureHandler(failureHandler())
              .successForwardUrl("/")
              .permitAll()
              .loginProcessingUrl("/login")
          .and().logout()
              .logoutSuccessUrl("/login?logout")
          .and().authorizeRequests()
              .antMatchers("/login").permitAll()
              .antMatchers(RequestMappings.CHANGE_PASSWORD).permitAll()
              .anyRequest().authenticated()
          .and().csrf()
              .csrfTokenRepository(csrfTokenRepository())
          .and().addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class);
      }
      

      现在,仍然有一种方法可以获取白页错误。如果在登录之前,您直接访问 localhost:8080/ui...。它会将您转发到 localhost:8080/login 页面。您登录。您将在 localhost:8080/ui/ 按预期查看所有内容。如果您删除最后一个正斜杠,那么您将收到白页错误。然后从那里事情可以在缓存中被弄脏。但是如果你回到root,你可以正常登录,一切都会正常工作。

      我认为发生了什么是登录前的 localhost:8080/ui 调用被缓存了,因为 index.html 页面在您重新登录并返回后从未​​加载过,您通过了授权检查,但它尝试加载......好吧,什么都没有,然后抛出一个错误。至少这是我的最佳猜测。

      无论如何,干杯!感谢您的帮助,让我们走上了正轨!

      【讨论】:

      • 酷,很高兴您发现了问题!请务必在此处标记正确答案
      猜你喜欢
      • 2015-04-26
      • 2012-07-06
      • 1970-01-01
      • 2016-06-13
      • 2021-03-11
      • 2017-02-02
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多