我们创建了一个模仿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作为root,我们有localhost:8080 / login(登录页面),localhost:8080 / ui(jQuery客户端)和localhost:8080 / api(restful web services,业务逻辑等)
我们正在寻找会话处理并转发到各个实体按预期工作。意味着会话按预期创建,转发正在按预期发生,等等。有一个例外。如果我登录,然后注销,然后直接转到localhost:8080 / ui它会转发我到登录页面。您登录后,它会将您转发回localhost:8080 / ui,但会显示" ACCESS DENIED"!
在跟踪数据库和客户端中的会话后,我发现数据库中存在两个会话。一个有权限,一个没有。客户保留没有!
还有其他人遇到过这个问题吗?有没有办法规避这个?
这是我经历的列表步骤,数据库会话跟踪和客户端验证。
session_id principal_name Client ------------------------------------------------------------ 1) go to localhost:8080 9229045c-27e0-410a-8711-45c56576d647 - X 2) login 2275db1c-fca4-4a2f-be73-e440599499d6 root X 3) logout cc917e68-b1c0-46a4-bbe3-6705ccf7a5fa - X 4) go to localhost:8080/ui --> forwards to localhost:8080/login cc917e68-b1c0-46a4-bbe3-6705ccf7a5fa - X 5) login -> forwards to localhost:8080/ui -> Access Denied 90d7931d-b265-42e2-a225-286bcf7d159c - X
d2fae0ac-9cf9-4287-8e38-51f64b0ab28d root
答案 0 :(得分:1)
好吧,经过几个小时,我们找到了解决行为似乎不一致的问题。意思有时你会登录并且它会保留正确的会话,你可以去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 /登录页面。你登录。你将在localhost:8080 / ui /按预期查看所有内容。如果删除最后一个正斜杠,则会出现白页错误。然后从那里可以搞砸缓存中的东西。但是如果你回到根目录,你可以正常登录,一切都会正常工作。
我认为发生的事情是登录前的localhost:8080 / ui调用正在被缓存,因为一旦你重新登录并返回后你就没有加载index.html页面,你通过了授权检查,但它试图加载......好吧,没有,然后抛出一个错误。至少这是我最好的猜测。
无论如何,干杯!感谢您的帮助,让我们走上正轨!
答案 1 :(得分:0)
最有可能的是,当您直接返回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);
}