我有一个 React 应用程序,该应用程序是在 Spring 应用程序中添加的,整个应用程序是使用 google 通过 spring oauth2 进行身份验证的。因此,当我打开 /logout 但它没有执行注销时,它正在重定向主页,所以如何做到这一点。我写这个是为了清除cookie,但没有用
return httpSecurity
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.sessionFixation().migrateSession()
.maximumSessions(1)
.expiredUrl("/login?expired"))
.authorizeHttpRequests(auth -> {
auth.anyRequest().authenticated();
}
)
.csrf(csrf -> {
csrf.disable();
})
.oauth2Login(withDefaults())
.logout((logout) -> {
logout.logoutUrl("/logout");
logout.invalidateHttpSession(true);
logout.logoutSuccessUrl("/");
logout.clearAuthentication(true);
logout.deleteCookies("auth_code", "JSESSIONID", "refreshToken", "Authorization")
;
})
.build();
您的用户有两个会话:一个在带有
oauth2Login
的 Spring OAuth2 客户端上,另一个在 Google 授权服务器上。
您实现的注销会结束 Spring OAuth2 客户端上的用户会话,而不是 Google 的客户端。
结果是,当用户再次登录您的 Spring 应用程序时,授权代码流程会默默完成:用户被重定向到 Google 授权服务器,因为他有一个活动会话,并且已经接受向您的 Spring OAuth2 客户端授予确定其请求的范围,他将被重定向回您的客户端,并带有授权代码,并且不会提示输入凭据。
您可能觉得这种行为是一个问题,因为您按如下方式配置了 Spring 应用程序:
spring-boot-starter-oauth2-client
默认值,即通过302
重定向到登录来回答对受保护资源的未经授权的请求(401
未经授权可能是单页和移动应用程序的更好选择)如果您更改上述任何一点,您会发现您的用户实际上已注销。您还可以添加一个可供匿名访问的端点,并在 Spring 的安全上下文中返回一些有关身份验证的数据,您应该看到用户实际上已从您的应用程序中注销(用户是匿名的,并且会话中不再有 OAuth2 令牌)。
如果您确实想从 Google 注销用户,您可以:
但是对于您的应用程序的用户来说,结束 Google 会话可能会是一次非常糟糕的体验。我要做的是使用我自己的授权服务器,并以 Google 作为身份提供商。然后,我会在 Spring 中配置 RP-Initiated Logout,这将结束 Spring 客户端上的会话,然后结束我的授权服务器上的会话,但活动用户的 Google 会话仍处于活动状态。
这样的授权服务器有很多选择:
spring-authorization-server
自己完成,这在您只需要“使用...登录”的情况下是合理的(无需创建登录和注册表、用户数据库等)