I've my custom implementation of Spring security in a Spring boot application. So I have my dependencies and I've a class named SecurityImpl which implements for me the login access. When I get on the browser I'm correctly asked to login with an alert. When I login I have access to all of the @RequestMapping of my Spring Controller correctly. But I remain always logged. Even if I delete the JSESSIONID from my browser, when I make another http request, I am allowed and a new JSESSIONID is created and sent to my browser.
One weird thing is that even when I access with the login for the first time, even when the cookie is authomatically generated, the expiration date is: 1969-12-31T23:59:59.000Z
I've tried to invalidate the session, to delete the cookies from the server, to logout in various ways but nothing. Once logged, I am always allowed.
Here my SecurityImpl.java class which configurates my Spring Security:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Configuration
@Component
public class SecurityImpl extends WebSecurityConfigurerAdapter implements AuthenticationProvider {
public static final String ROLE_ADMIN = "ROLE_ADMIN";
public static final String ROLE_USER = "ROLE_USER";
@Autowired UtenteDao utenteDao;
/* authentication provider part */
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials().toString();
String ruolo = "";
Optional<Utente> utenteOptional = utenteDao.findByCodiceFiscaleAndPassword(username, password);
if(utenteOptional.isPresent()){
ruolo = utenteOptional.get().getRuolo();
}
if(ROLE_ADMIN.equals(ruolo)) {
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority(ROLE_USER));
grantedAuths.add(new SimpleGrantedAuthority(ROLE_ADMIN));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
} else if(ROLE_USER.equals(ruolo)){
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority(ROLE_USER));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
} else {
throw new BadCredentialsException("Autenticazione fallita");
}
}
@Override
public boolean supports(Class<?> auth) {
return auth.equals(UsernamePasswordAuthenticationToken.class);
}
/* websecurity adapter part: erase it if you don't want login alert but default spring login web page */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this); //this because it is either a WebSecurityAdapter than an AuthenticationProvider
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic()
.and()
.logout().clearAuthentication(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/test")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true);
}
/* per non filtrare con il login alcuni path */
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/test");
}
}
It doesn't work: when I go to /logout I'm redirected to /test correctly but when I ask for a forbidden path I'm allowed without any login.
Then I tried some solution in my @RestController:
@RequestMapping("/logout")
public String logoutPage (UsernamePasswordAuthenticationToken token) {
token.eraseCredentials();
token.setAuthenticated(false);
SecurityContextHolder.getContext().setAuthentication(null);
return "<h1>Logout effettuato con successo.</h1>";
}
then I tried:
@RequestMapping(value = "/logout")
public String loadApp(HttpServletRequest request) {
HttpSession session= request.getSession(false);
SecurityContextHolder.clearContext();
if(session != null) {
session.invalidate();
}
return "<h1>Logout effettuato con successo.</h1>";
}
Then, as a desperate, I tried:
@RequestMapping("/logout")
public String logoutDo(HttpServletRequest request){
HttpSession session= request.getSession(false);
SecurityContextHolder.clearContext();
session= request.getSession(false);
if(session != null) {
session.invalidate();
}
for(Cookie cookie : request.getCookies()) {
cookie.setMaxAge(0);
}
return "<h1>Logout effettuato con successo.</h1>";
}
I tried to use these methods and contemporarily delete my cookie from the browser. I've also tried to preauthorize forbidden method with the annotation @PreAuthorize, in the case they would be allowed (when you open a new browser, before first login, they are NOT allowed even without @PreAuthorize, but when login is made, IS FOREVER!)
The problem was the absence of the usage of showForm(). Without it, yes I insert my credentials within a Javascript alert which is presented to me. But no logout is possible.
So the code changes this way:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic()
.and()
.logout().clearAuthentication(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/test")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.