Spring Security: hasAuthority, hasRole и PreAuthorize не работает - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь протестировать мой веб-API, защищенный стандартными аннотациями и методами Spring Security. Я просмотрел все варианты на сайте, ничего не помогло, вот код. Без ролей все работает нормально. Я уже несколько дней мучаюсь с этой проблемой. Буду благодарен за помощь, спасибо.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImp userDetailsService;

    @Autowired
    JwtFilter jwtFilter;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/authenticate").permitAll()
                .antMatchers(HttpMethod.GET,"/userData").permitAll()
                .antMatchers(HttpMethod.GET,"/allUsers").hasAuthority("ROLE_ADMIN")
                .anyRequest().authenticated()
                .and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint())
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }

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

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

Класс контроллера

@RestController
public class AuthenticationController {

    @Autowired
    public AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsServiceImp userDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserRepository userRepository;


    @RequestMapping(value = "/userData", method = RequestMethod.GET)
    public String hello(){
        return "Hello new User";
    }

    @RequestMapping(value = "/allUsers", method = RequestMethod.GET)
    public List<UserD> findAll(){
        return userRepository.findAll();
    }

    @RequestMapping(value = "/authenticate", method = RequestMethod.POST)
    public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest jwtRequest) throws Exception{
        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(jwtRequest.getName(), jwtRequest.getPassword()));
        }catch(BadCredentialsException e){
            throw new Exception("Incorrect username and password", e);
            }
        final UserD userD = (UserD)userDetailsService.loadUserByUsername(jwtRequest.getName());

        final String token = jwtUtil.generateToken(userD.getName(), userD.getRole());

        Map<Object, Object> model = new HashMap<>();
        model.put("username", jwtRequest.getName());
        model.put("token", token);

        return ResponseEntity.ok(model);
    }
}

Если antMatchers(HttpMethod.GET,"/allUsers").permitAll(), затем он возвращает пользователей в порядке

UserDetailsServiceImp

@Service
public class UserDetailsServiceImp implements UserDetailsService {

    @Autowired
    UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByName(username).get(0);
    }
}

и данных пользователя с добавлением ролей

@Component
public class DataInitializer implements CommandLineRunner {

    @Autowired
    UserRepository userRepository;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    public void run(String... args) throws Exception {
        UserD user = new UserD();
        user.setName("user");
        user.setPassword(passwordEncoder.encode("password"));
        user.setRole("ROLE_USER");
        userRepository.save(user);

        UserD admin = new UserD();
        admin.setName("admin");
        admin.setPassword(passwordEncoder.encode("password"));
        admin.setRole("ROLE_ADMIN");
        userRepository.save(admin);
     }
}

это то, что возвращает база данных

response on this url

1 Ответ

0 голосов
/ 12 марта 2020

Сначала я хочу кое-что прояснить, что может помочь вам точно определить проблему:

Ваш UserDetailsServiceImp извлекает имя пользователя и роль из базы данных, LDAP или другого хранилища? какая роль извлекается из базы данных, LDAP или другого хранилища? у него уже есть префикс "ROLE_" или нет?

если роль, полученная из базы данных, - "ADMIN", вы не должны добавлять ROLE_ самостоятельно, когда вызываете hasAuthority ().

.antMatchers(HttpMethod.GET,"/allUsers").hasAuthority("ADMIN")

И если это не так, включите отладку в журнале, чтобы увидеть, что именно происходит с запросом / allUsers.


ОБНОВЛЕНИЕ: И один я подозревал, что вы реализовали UserDetailsServiceImp.

Вы должны убедиться, что роль была задана в деталях пользователя. в вашей реализации кажется, что вы запрашивали непосредственно из БД, не будучи уверенным, что вы задали роль в userDetails.

return userRepository.findByName(username).get(0);

Вот что должно произойти:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    //assume, there is only one user with the username
    UserD user = userRepository.findByUsername(username);
    if (user == null) {
        throw new UsernameNotFoundException("User not found with username: " + username);
    }
    List<GrantedAuthority> roles = new ArrayList<>();
    //assume, there is only one role for the user
    roles.add(new SimpleGrantedAuthority(user.getRole()));
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
                roles);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...