web-dev-qa-db-fra.com

Spring Security Toujours renvoyant 403 interdit, accès refusé

Je veux permettre à l'administrateur d'accéder à la page d'administration et de faire des tâches d'administration, mais lorsque j'essaie de le faire en définissant que l'URL avec/admin/** ne peut être accessible que par l'utilisateur avec le rôle admin, il renvoie 403 Interdit, accès refusé. Mais l'utilisateur a des autorisations définies sur ROLE_ADMIN que j'ai vérifiées. Qu'est-ce que je fais mal?

Mon contrôleur pour la connexion utilisateur

@RestController
public class UserController {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthorityService authorityService;

    @Autowired
    private UserAuthorityService userAuthorityService;

    @Autowired
    TokenUtils tokenUtils;

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/api/login", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> login(@RequestBody LoginDTO loginDTO) {
        try {
//          System.out.println(loginDTO.getUsername() + " " + loginDTO.getPassword());
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                    loginDTO.getUsername(), loginDTO.getPassword());

            Authentication authentication = authenticationManager.authenticate(token);

            SecurityContextHolder.getContext().setAuthentication(authentication);

            UserDetails details = userDetailsService.loadUserByUsername(loginDTO.getUsername());

            return new ResponseEntity<String>(tokenUtils.generateToken(details), HttpStatus.OK);
        } catch (Exception ex) {
            return new ResponseEntity<String>("Invalid login", HttpStatus.BAD_REQUEST);
        }
    }

    @RequestMapping(value = "/api/register", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> register(@RequestBody RegisterDTO registerDTO) {
        try {
            System.out.println(registerDTO);
            User user = userService.findUserByUsername(registerDTO.getUsername());
//            // Check if user with that username exists
            if(user != null){
                // User with that username is found
                return new ResponseEntity<String>("User with that username exists", HttpStatus.BAD_REQUEST);
            }
            // We need to save the user so his ID is generated
            User newUser = userService.saveUser(new User(registerDTO));

            UserAuthority userAuthority = userAuthorityService.save(new UserAuthority(newUser, authorityService.findOneByName("User")));

            Set<UserAuthority> authorities = new HashSet<>();
            authorities.add(userAuthority);

            newUser.setUserAuthorities(authorities);
            User savedUser = userService.save(newUser);
            return new ResponseEntity<String>("You have registered successfully with username " + savedUser.getUsername(), HttpStatus.OK);
        } catch (Exception ex) {
            return new ResponseEntity<String>("Invalid register", HttpStatus.BAD_REQUEST);
        }
    }
}

Je peux dire que je teste mon application avec le facteur et que la connexion et l'enregistrement fonctionnent correctement. Lorsque l'utilisateur est connecté, je peux le jeton avec les données et les autorités d'utilisateurs correctes, mais pourquoi lorsque j'essaie d'accéder à/admin/building/add url, il renvoie une erreur 403?

Mon contrôleur pour ajouter un bâtiment pour la page d'administration:

@RestController
public class BuildingController {

    @Autowired
    private BuildingService buildingService;

    @RequestMapping(value = "/admin/building/add", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> addBuilding(@RequestBody BuildingDTO buildingDTO) {
        try{
            Building newBuilding = new Building(buildingDTO);
            return new ResponseEntity<String>(newBuilding.getName(), HttpStatus.OK);
        }catch (Exception ex) {
            return new ResponseEntity<String>("Data was not valid", HttpStatus.BAD_REQUEST);
        }
    }
}

My SecurityConfiguration.Java

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    public void configureAuthentication(
            AuthenticationManagerBuilder authenticationManagerBuilder)
            throws Exception {

        authenticationManagerBuilder
                .userDetailsService(this.userDetailsService).passwordEncoder(
                        passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public AuthenticationTokenFilter authenticationTokenFilterBean()
            throws Exception {
        AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter();
        authenticationTokenFilter
                .setAuthenticationManager(authenticationManagerBean());
        return authenticationTokenFilter;
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
                .antMatchers("/index.html", "/view/**", "/app/**", "/", "/api/login", "/api/register").permitAll()
                // defined Admin only API area 
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest()
                .authenticated()
                .and().csrf().disable();
                //if we use AngularJS on client side
//              .and().csrf().csrfTokenRepository(csrfTokenRepository()); 

        //add filter for adding CSRF token in the request 
        httpSecurity.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);

        // Custom JWT based authentication
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(),
                UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * If we use AngularJS as a client application, it will send CSRF token using 
     * name X-XSRF token. We have to tell Spring to expect this name instead of 
     * X-CSRF-TOKEN (which is default one)
     * @return
     */
    private CsrfTokenRepository csrfTokenRepository() {
          HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
          repository.setHeaderName("X-XSRF-TOKEN");
          return repository;
    }
  }

Je dois mentionner que j'utilise Angularjs pour l'interface, mais même ainsi, je peux me connecter et les autorités correctes sont affichées pour cet utilisateur. Mais pour une raison quelconque, je ne peux pas accéder à la page d'administration, même si je me connecte en tant qu'administrateur.

J'ai également essayé .hasAuthority("ROLE_ADMIN") et .hasRole("ROLE_ADMIN") (qui affiche une erreur pour ROLE_) et je l'ai donc changé en .hasRole("ADMIN") mais cela ne fonctionne toujours pas.

Dans la base de données, le rôle d'administrateur est enregistré sous ROLE_ADMIN.

6
P3P5

Essayez comme ceci:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static String REALM="MY_TEST_REALM";

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("tom").password("abc123").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

      http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/user/**").hasRole("ADMIN")
        .and().httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint())
        .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created.
    }

    @Bean
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
        return new CustomBasicAuthenticationEntryPoint();
    }

    /* To allow Pre-flight [OPTIONS] request from browser */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }
}

Pour un exemple de configuration complet: Secure Spring REST utilisant l'authentification de base

10
FuSsA
    import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();// We don't need sessions to be created.
    }

}

Cela l'a fait pour moi. Maintenant, je peux soumettre mes demandes de publication avec succès

0
Ajay Menon