antMatchers & permitAll doesn't let me visit the REST point

孤街浪徒 提交于 2020-06-17 16:20:53

问题


The following line doesn't let me visit GET: /api/topics without a bearer token. It works if I apply a token. Am I missing something? Isn't permitAll supposed to do that?

.antMatchers("/api/topics/**").permitAll()

By the way, I tried with /api/topics** and it didn't work as well.

Error:

{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}

Result without a token (the broken part). I want it to let me through.

Result with a token. It works as intended:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/topics/**").permitAll()
                .antMatchers("/api/users/**").permitAll()
                .anyRequest().authenticated();
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
@RestController
@RequestMapping("/api/topics")
public class TopicController {

    @Autowired
    private TopicService topicService;

    @Autowired
    private UserService userService;

    @Autowired
    private TopicMapper topicMapper;

    /**
     * Gets all topics.
     *
     * @return the topics.
     */
    @GetMapping
    public ResponseEntity<List<TopicDTO>> getAll() {
        return ResponseEntity.ok(topicMapper.toTopicDTOs(topicService.getAll()));
    }

    /**
     * Gets topic by id.
     *
     * @param id the id.
     * @return the topic.
     */
    @GetMapping("/{id}")
    public ResponseEntity<TopicDTO> get(@PathVariable("id") Long id) {
        Optional<TopicEntity> topicEntity = topicService.get(id);
        return topicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.notFound().build());
    }

    /**
     * Creates a new topic.
     *
     * @param topicDTO the topic DTO.
     * @return the new topic DTO.
     */
    @PostMapping
    public ResponseEntity<TopicDTO> create(@RequestBody TopicDTO topicDTO) {
        UserEntity userEntity = userService.get(topicDTO.getUserId()).orElseThrow(() -> new IllegalArgumentException("User does not exist."));

        TopicEntity topicEntity = topicMapper.toTopicEntity(topicDTO);
        topicEntity.setId(null);
        topicEntity.setUser(userEntity);

        Optional<TopicEntity> createdTopicEntity = topicService.create(topicEntity);

        return createdTopicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.status(HttpStatus.CONFLICT).build());
    }

    /**
     * Updates an existing topic.
     * @param id the topic id.
     * @param topicDTO the topic DTO.
     * @return the updated topic DTO.
     */
    @PutMapping("/{id}")
    public ResponseEntity<TopicDTO> update(@PathVariable("id") Long id, @RequestBody TopicDTO topicDTO) {
        UserEntity userEntity = userService.get(topicDTO.getUserId()).orElseThrow(() -> new IllegalArgumentException("User does not exist."));

        TopicEntity topicEntity = topicMapper.toTopicEntity(topicDTO);
        topicEntity.setId(id);
        topicEntity.setUser(userEntity);

        Optional<TopicEntity> updatedTopicEntity = topicService.update(topicEntity);

        return updatedTopicEntity.map(entity -> ResponseEntity.ok(topicMapper.toTopicDTO(entity))).orElseGet(() -> ResponseEntity.badRequest().build());
    }

    /**
     * Deletes an existing topic.
     * @param id the topic id.
     * @return the status code.
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable("id") Long id) {
        if (topicService.get(id).isPresent()) {
            topicService.delete(id);
            return ResponseEntity.ok().build();
        }

        return ResponseEntity.notFound().build();
    }

}
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("trusted")
                .secret(bCryptPasswordEncoder.encode("secret"))
                .authorizedGrantTypes("password", "get_token", "refresh_token")
                .scopes("read", "write")
                .autoApprove(true)
                .accessTokenValiditySeconds(15 * 60)
                .refreshTokenValiditySeconds(30 * 60);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore);
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

}
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration {

}

回答1:


Because @EnableResourceServer will add its filter chain at order=3 by default.As for WebSecurityConfigurerAdapter implementation, adds its own filterchain at the order=100, as a result, request first goes through filter chain of set by @EnableResourceServer where everything is protected unless you provide token and that's why you are getting that behavior. Try to add order bellow 3 like @Order(2) annotation to your WebSecurityConfigurerAdapter implementation.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Order(2) <<---  add this
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  ...
}

For more information read: Changing the Filter Order




回答2:


There is a mistake with URL patterns in antMatchers.

By default the pattern like /api/topics/** doesn't match /api/topics.

It matches only /api/topics/ and after slash can be zero or more symbols

For fixing this case can be several solutions:

  1. Change the pattern in existing antMatchers to next /api/topics**
  2. Use mvcMatchers instead of antMatchers. mvcMatchers("/api/topics").permitAll()

mvcMatchers - will use the same rules that Spring MVC uses for matching. For example, often times a mapping of the path "/path" will match on "/path", "/path/", "/path.html", etc.

More information about antMatchers can be found here

More information about mvcMatchers can be found here



来源:https://stackoverflow.com/questions/61031784/antmatchers-permitall-doesnt-let-me-visit-the-rest-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!