我使用Spring安全性(4.0.2.RELEASE)来保护我的应用程序。
我可以正常登录并且我的身份验证的URL受到保护,但是当我尝试注销时,我会不断获得302 POST响应,然后重定向到我配置的failureUrl(“/ cms / login?error”)。
这是我的WebSecurityConfig类
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/*").permitAll()
.antMatchers("/cms/*").authenticated()
.antMatchers("/cms/*/*").authenticated()
.antMatchers("/cms/*/*/*").authenticated().and()
.formLogin()
.loginPage("/cms/login")
.defaultSuccessUrl("/cms/login?success")
.failureUrl("/cms/login?error")
.permitAll().and()
.logout()
.logoutUrl("/cms/login?logout")
.logoutSuccessUrl("/cms/login")
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("u")
.password("p")
.roles("USER");
}
@Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
}
这是我的登录控制器:
@Slf4j
@Controller
@RequestMapping(value = {"/cms", "/cms/login"})
public class CmsLoginController extends CmsBaseController
{
@RequestMapping
public ModelAndView handleLogin(HttpServletResponse request,
Model model,
@RequestParam(value = LOGIN_SUCCESS, required = false) String success,
@RequestParam(value = LOGIN_ERROR, required = false) String error,
@RequestParam(value = LOGOUT, required = false) String logout)
{
try
{
if (success != null)
{
setLoggedIn(true);
request.sendRedirect(XXXXX);
}
if (error != null)
{
model.addAttribute(LOGIN_ERROR, "Invalid username and password!");
}
if (logout != null)
{
model.addAttribute(LOGOUT, "You've been logged out successfully.");
setLoggedIn(false);
}
return new ModelAndView(CMS_CONTEXT + LOGIN_URL);
}
catch(Exception e)
{
setLoggedIn(false);
log.error(e.toString(), e);
return new ModelAndView(ERROR_VIEW_NAME);
}
}
}
为了记录,我最初使用注销功能正常工作,但我必须介绍一些已经破坏它的更改...
有什么想法? 谢谢
答案 0 :(得分:0)
spring进行不必要的注销逻辑以进行重定向 我有点烦。
默认行为应该是直接的,而不是重定向,并且它们可以保留特殊情况的规定。
在配置方法中使用以下内容
.logout().logoutUrl("/api/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
System.out.println("success");
}
});
此链接的积分 https://www.codeproject.com/Tips/521847/Logout-Spring-s-LogoutFilter
答案 1 :(得分:0)
我认为问题是CSRF过滤器。在Spring Security 4中,CSRF防护默认情况下处于打开状态,每个POST请求都需要一个CSRF令牌。
如果您从以前的Spring版本中迁移代码,那么很有可能这就是问题所在。
要进行快速测试,请将public static class EntityHelper
{
public static IEnumerable<UpdateFieldDefinition> GetUpdateDefinition<T>(this T entity)
{
return entity.GetType().GetProperties()
.Where(x =>
{
switch (x.Name)
{
case nameof(BaseEntity.Id):
case nameof(BaseEntity.CreationDate):
case nameof(BaseEntity.LastModifiedDate):
case nameof(BaseEntity.CreatorId):
case nameof(BaseEntity.LastModifierUserId):
return false;
default:
return true;
}
})
.Select(x => new UpdateFieldDefinition(x.Name, x.GetValue(entity)));
}
}
添加到您的配置中。如果这样有效,则请转回CSRF保护并将CSRF令牌以某种方式添加到POST注销请求中。