Spring MVC webapp + REST: проблема авторизации - PullRequest
0 голосов
/ 29 апреля 2020

Я строю систему CRM с Spring MVC. Сейчас я добавляю поддержку REST для системы, но Spring Security по какой-то причине предоставит неавторизованному пользователю с ролью «EMPLOYEE» доступ к методу POST (для создания нового клиента в системе). Все работает правильно с формами и аутентификацией. Просто по какой-то причине происходит сбой авторизации специально для RestController.

Я использую PostgreSQL для хранения клиентов и пользователей, а также для аутентификации.

Примечание: я использую "/ customer "для REST и в качестве точки входа для веб-приложений.

Вот мой SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers(HttpMethod.GET, "/customer").hasRole("EMPLOYEE")
            .antMatchers(HttpMethod.POST, "/customer").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/showForm*").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/save*").hasAnyRole("MANAGER", "ADMIN")
            .antMatchers("/customer/delete").hasRole("ADMIN")
            .antMatchers("/customer/**").hasRole("EMPLOYEE")
            .antMatchers("/resources/**").permitAll()
            .and()
            .httpBasic()
            .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/authenticate")
            .permitAll()
            .and()
            .logout().permitAll()
            .and()
            .exceptionHandling().accessDeniedPage("/access-denied")
            .and()
            .csrf().disable();
    }

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

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }
}

А вот мой RestController:

@RestController
@RequestMapping("/customer")
public class CustomerRestController {

    @Autowired
    private CustomerService customerService;

    @GetMapping
    public List<Customer> getCustomers() {
        return customerService.getCustomers();
    }

    @GetMapping("/{customerId}")
    public Customer getCustomer(@PathVariable int customerId) {
        Customer customer = customerService.getCustomer(customerId);
        if (customer == null) throw new CustomerNotFoundException("Customer not found: id = " + customerId);
        return customer;
    }

    @PostMapping
    public Customer addCustomer(@RequestBody Customer customer) {
        customer.setId(0);
        customerService.saveCustomer(customer);
        return customer;
    }
}

Обновление:

  1. Я попытался сопоставить RestController с другим путем - не сработало.
  2. Я также попытался разбить SecurityConfig на несколько точек входа - не сработало и по какой-то причине также начал автоматический вход.
  3. Добавлен @Secured ({"ROLE_MANAGER", "ROLE_ADMIN"}) перед методом Post в RestController - тот же результат.

Кажется, что с моим RestController Spring не заботится о ролях пользователей вообще.

1 Ответ

0 голосов
/ 30 апреля 2020

После часов исследований, проб и ошибок все работает как надо. Ключевой проблемой были недостающие звездочки в путях для методов. Вместо «/ customer» это должно быть «/ customer / **». Я также немного изменил путь для веб-форм и поддержки REST, чтобы избежать путаницы и облегчить поддержку. В любом случае, вот обновленный SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

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

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }

    @Configuration
    @Order(1)
    public static class ApiSecurityConfig extends WebSecurityConfigurerAdapter {

        @Bean
        public AuthenticationEntryPoint entryPoint() {
            return new CustomAuthenticationEntryPoint();
        }

        @Bean
        public AccessDeniedHandler accessDeniedHandler() {
            return new CustomAccessDeniedHandler();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().antMatcher("/api/**")
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/api/customers/**").hasRole("EMPLOYEE")
                .antMatchers(HttpMethod.POST, "/api/customers/**").hasAnyRole("MANAGER", "ADMIN")
                .and()
                .httpBasic()
                .authenticationEntryPoint(entryPoint())
                .and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    }

    @Configuration
    @Order(2)
    public static class FormSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                .antMatchers("/customer/showForm*").hasAnyRole("MANAGER", "ADMIN")
                .antMatchers("/customer/save*").hasAnyRole("MANAGER", "ADMIN")
                .antMatchers("/customer/delete").hasRole("ADMIN")
                .antMatchers("/customer/**").hasRole("EMPLOYEE")
                .antMatchers("/resources/**").permitAll()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/authenticate")
                .permitAll()
                .and()
                .logout().permitAll()
                .and()
                .exceptionHandling().accessDeniedPage("/access-denied");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...