以下行不允许我在没有承载令牌的情况下访问GET: /api/topics
。如果我应用令牌,它会起作用。我想念什么吗?是不是permitAll应该这样做?
.antMatchers("/api/topics/**").permitAll()
顺便说一句,我尝试使用/api/topics**
,但效果不佳。
错误:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
没有令牌的结果(损坏的部分)。我希望它让我通过。
带有令牌的结果。它按预期工作:
@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 {
}
答案 0 :(得分:1)
antMatchers中的网址格式有误。
默认情况下,/api/topics/**
之类的模式与/api/topics
不匹配。
它仅与/api/topics/
匹配,并且斜杠后可以是零个或多个符号
要解决此问题,可以采用几种解决方案:
/api/topics**
mvcMatchers("/api/topics").permitAll()
mvcMatchers-将使用与Spring MVC相同的规则 匹配。例如,通常路径“ / path”的映射会 在“ /path”、“/path/”、“/path.html”等上匹配。
有关antMatchers的更多信息,请参见here
有关mvcMatchers的更多信息,请参见here
答案 1 :(得分:0)
因为@EnableResourceServer
默认情况下会在order = 3处添加其过滤器链。对于WebSecurityConfigurerAdapter
实现,它会在order = 100处添加其自己的过滤器链,因此,请求首先通过过滤器链由@EnableResourceServer
设置,其中所有内容都受到保护,除非您提供令牌,这就是为什么您会得到这种行为。尝试在您的@Order(2)
实现中添加像WebSecurityConfigurerAdapter
这样的命令波纹管3。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Order(2) <<--- add this
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
有关更多信息,请阅读:Changing the Filter Order