无法使用 JdbcTokenStore 在 Spring OAuth2 中注销
Unable to logout in Spring OAuth2 using JdbcTokenStore
Spring 带有 JdbcTokenStore 的 OAuth2 - 已使用自定义登录页面,如以下代码片段中所编码。
来自不同的在线资源,例如here Spring 安全似乎有一个内置端点 /logout 来注销用户,但这似乎对我不起作用。当我到达该端点时,它会重定向回自定义登录页面,这很好,但不一致。使用多个选项卡时,它有时会起作用,但并非每次都起作用。还注意到 Spring 创建的 cookie 也没有清除。
下面定义的 WebSecurityConfigurerAdapter 有问题吗?
@Configuration
@Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/homepage", false)
.failureUrl("/login?error=true")
.and()
.requestMatchers().antMatchers("/login", "/homepage", "/login?error=true", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests().anyRequest().authenticated();
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
}
一旦内置注销功能开始工作,最好也删除在数据库中创建的令牌。尝试了一些可能的答案 online 但它们不起作用。任何指点将不胜感激?
我可以 post 更多代码片段,如果它有助于提供更多清晰度的话。
我们终于成功了 - 希望这对同一条船上的其他人有所帮助。
如果您不需要下面的代码片段中的会话管理配置,您可以忽略它。
@Configuration
@Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.invalidSessionUrl("/login")
.sessionAuthenticationErrorUrl("/login")
.and()
.formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/homepage", false)
.failureUrl("/login?error=true")
.and()
.requestMatchers()
.antMatchers("/", "/login", "/logout", "/homepage", "/login?error=true", "/oauth/authorize", "/oauth/confirm_access")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").invalidateHttpSession(true)
.permitAll()
.and().authorizeRequests()
.antMatchers("/login**")
.permitAll().anyRequest().authenticated();
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
}
创建一个注销控制器以及上面的方法就可以了
@Controller
public class LogoutController {
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(HttpServletRequest request, HttpServletResponse response, Model model) {
/* Getting session and then invalidating it */
HttpSession session = request.getSession();
if (session != null) {
session.invalidate();
}
HandleLogOutResponse(response, request);
return "logout";
}
private void HandleLogOutResponse(HttpServletResponse response, HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
cookie.setValue(null);
cookie.setPath("/");
response.addCookie(cookie);
}
}
您可以使用如下所示的简单函数注册您的视图
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/homepage").setViewName("homepage");
registry.addViewController("/logout").setViewName("logout");
}
Spring 带有 JdbcTokenStore 的 OAuth2 - 已使用自定义登录页面,如以下代码片段中所编码。
来自不同的在线资源,例如here Spring 安全似乎有一个内置端点 /logout 来注销用户,但这似乎对我不起作用。当我到达该端点时,它会重定向回自定义登录页面,这很好,但不一致。使用多个选项卡时,它有时会起作用,但并非每次都起作用。还注意到 Spring 创建的 cookie 也没有清除。
下面定义的 WebSecurityConfigurerAdapter 有问题吗?
@Configuration
@Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/homepage", false)
.failureUrl("/login?error=true")
.and()
.requestMatchers().antMatchers("/login", "/homepage", "/login?error=true", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests().anyRequest().authenticated();
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
}
一旦内置注销功能开始工作,最好也删除在数据库中创建的令牌。尝试了一些可能的答案 online 但它们不起作用。任何指点将不胜感激?
我可以 post 更多代码片段,如果它有助于提供更多清晰度的话。
我们终于成功了 - 希望这对同一条船上的其他人有所帮助。
如果您不需要下面的代码片段中的会话管理配置,您可以忽略它。
@Configuration
@Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.invalidSessionUrl("/login")
.sessionAuthenticationErrorUrl("/login")
.and()
.formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/homepage", false)
.failureUrl("/login?error=true")
.and()
.requestMatchers()
.antMatchers("/", "/login", "/logout", "/homepage", "/login?error=true", "/oauth/authorize", "/oauth/confirm_access")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").invalidateHttpSession(true)
.permitAll()
.and().authorizeRequests()
.antMatchers("/login**")
.permitAll().anyRequest().authenticated();
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
}
创建一个注销控制器以及上面的方法就可以了
@Controller
public class LogoutController {
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(HttpServletRequest request, HttpServletResponse response, Model model) {
/* Getting session and then invalidating it */
HttpSession session = request.getSession();
if (session != null) {
session.invalidate();
}
HandleLogOutResponse(response, request);
return "logout";
}
private void HandleLogOutResponse(HttpServletResponse response, HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
cookie.setValue(null);
cookie.setPath("/");
response.addCookie(cookie);
}
}
您可以使用如下所示的简单函数注册您的视图
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/homepage").setViewName("homepage");
registry.addViewController("/logout").setViewName("logout");
}