简体   繁体   English

Spring Security无法注销

[英]Spring security cannot logout

I've my custom implementation of Spring security in a Spring boot application. 我在Spring引导应用程序中自定义了Spring安全性实现。 So I have my dependencies and I've a class named SecurityImpl which implements for me the login access. 因此,我有依赖关系,并且有一个名为SecurityImpl的类,该类为我实现了登录访问。 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. 登录时,我可以正确访问我的Spring Controller的所有@RequestMapping。 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. 即使我从浏览器中删除了JSESSIONID,当我发出另一个http请求时,我也被允许并创建一个新的JSESSIONID并将其发送到我的浏览器。

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 一件奇怪的事情是,即使我是第一次使用登录名访问,即使以合法方式生成了Cookie,其过期日期也都是: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. 我试图使会话无效,从服务器中删除cookie,以各种方式登出,但什么也没有。 Once logged, I am always allowed. 登录后,我总是被允许的。

Here my SecurityImpl.java class which configurates my Spring Security: 这是我的SecurityImpl.java类,用于配置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. 它不起作用:当我进入/ logout时,我被正确地重定向到/ test,但是当我请求一个禁止的路径时,无需任何登录即可被允许。

Then I tried some solution in my @RestController: 然后我在@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. 我尝试使用这些方法,并同时从浏览器中删除了我的cookie。 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!) 我还尝试了使用注释@PreAuthorize对禁止的方法进行预授权,以防它们被允许使用(当您打开新的浏览器时,在首次登录之前,即使没有@PreAuthorize也不允许使用它们,但是在进行登录时,IS永远!)

The problem was the absence of the usage of showForm(). 问题是缺少showForm()的用法。 Without it, yes I insert my credentials within a Javascript alert which is presented to me. 没有它,是的,我将凭据插入显示给我的Javascript警报中。 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);


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM