使用 oauth2 和 Google/Azure 身份验证服务器在 java 应用程序中注销时出现问题

Problem to logout in java app with oauth2 and Google / Azure auth server

我遇到了问题,需要一些建议。 情况如下,我有一个非常简单的 java 模块,具有 spring 安全性和受保护的 HTML 页面。该模块唯一要做的就是针对 Google / Azure 进行身份验证,如果凭据正确,它会将我带到 HTML 页面。实施 OAuth2 和 Spring 安全性 5. 身份验证没有问题,我获得了 idTokens、访问令牌和刷新令牌(对于 Azure)。 尝试注销时出现问题(HTML 中的按钮调用“app/logogut”URL)。我看到引用本地安全上下文的内容已删除,没有 cookie,浏览器存储中也没有任何内容,但是,外部服务器 (Google / Azure) 上的会话仍然处于活动状态,当我刷新页面我仍然登录。 如果我用 Gmail 打开一个新标签,我直接进入而不登录,如果我从 Gmail 注销,当我现在刷新第一个标签时,它会询问用户并再次通过。我的问题是我是否缺少注销的内容以通过 Spring 安全性完全关闭会话?

此外,尝试对每个服务器的 URL 执行 GET 以注销,这似乎可行,但这样做并不可取 -CORS 问题 :(-.

我的安全配置

文内

 @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/", "/login**").permitAll()
            .anyRequest().authenticated()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/app/logout"))
            .addLogoutHandler(new HeaderWriterLogoutHandler(
                    new ClearSiteDataHeaderWriter(
                            ClearSiteDataHeaderWriter.Directive.CACHE,
                            ClearSiteDataHeaderWriter.Directive.COOKIES,
                            ClearSiteDataHeaderWriter.Directive.STORAGE)))
            .and()
            .oauth2Login()
            .and().csrf().disable()
    ;
}

我的控制器

 @Autowired
@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/restricted")
public String restricted() throws IOException, URISyntaxException {
    URL resource = getClass().getClassLoader().getResource("static\Protected.html");
    if (resource == null) {
        throw new IllegalArgumentException("file not found!");
    } else {

        File html = new File(resource.toURI());
        List<String> strings = Files.readLines(html, StandardCharsets.UTF_8);
        StringBuffer sb = new StringBuffer();
        for (String s : strings) {
            sb.append(s);
        }
        return sb.toString();


    }

}

HTML 页面

如有任何帮助,我们将不胜感激!

提前致谢

您可能需要告诉 Spring 安全在注销时使 http 会话无效:

.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/app/logout"))
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true) 

或者根据您处理授权服务器的方式,重定向到处理注销的控制器,请参阅

通常您可以在注销控制器中调用 session.invalidate() 来结束 oauth2 登录。

终于,经过这么长时间,我找到了解决问题的办法。 根据 Spring 文档 (https://docs.spring.io/spring-security/site/docs/5.2.x/reference/html/oauth2.html#oauth2login-advanced-oidc-logout),我发现了一些所谓的单点退出,如果在 application.properties 中指定了 issuer-uri 就可以实现。这个 uri returns a json 其中,在其他数据中,是 end_session_endpoint url.

现在你可以像这样配置 OidcClientInitiatedLogoutSuccessHandler

这允许在从我的应用程序注销时调用先前的处理程序并使授权服务器中的会话无效。

非常感谢您的帮助