我正在尝试在这个小项目上实现SpringSecurity机制,这将限制角色与请求URL的交互。
我有两个角色 USER 和 ADMIN , USER 可以看到项目,但不能添加或删除它们,而 ADMIN 可以做到。
现在是问题所在,以某种方式允许 USER 角色的请求,甚至是未经身份验证的用户创建/删除/读取项目的请求。在我看来,我的应用程序在某处配置不正确。
SecurityConfig:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}12345").roles("USER").and()
.withUser("admin").password("{noop}12345").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests()
.antMatchers("api/**").hasRole("ADMIN")
.antMatchers("api/items", "api/items/").hasRole("USER")
.anyRequest().authenticated()
.and().csrf().disable().headers().frameOptions().disable();
}
}
控制器:
@RestController
public class ItemController {
@Autowired
private ItemService itemService;
@GetMapping("/api/items")
public List<Item> getItems() {
return itemService.getAllItems();
}
@PostMapping(value = "/api/addItem",consumes = {"application/json"},produces = {"application/json"})
@ResponseBody
public Item addItem(@RequestBody Item item) {
itemService.addItem(item);
return item;
}
@DeleteMapping(value = "api/deleteItem/{id}")
@ResponseBody
public String deleteItem(@PathVariable int id) {
itemService.deleteItem(id);
return "Deleted";
}
}
我正在将请求发送到以下URL:
http://localhost:8080/api/items // GET
http://localhost:8080/api/addItem // POST
http://localhost:8080/api/deleteItem/4 // DELETE
答案 0 :(得分:3)
您是否尝试过将斜线添加到您的antmatcher模式中,例如:
antMatchers("/api/**").hasRole("ADMIN")
Spring文档提到:
注意:模式和路径必须都是绝对的,或者都必须是相对的,才能使两者匹配。因此,建议此实现的用户清理模式,以便在模式使用的上下文中使用“ /”作为前缀。
此外,Spring安全性使用表示的所有匹配规则中的第一个匹配项。我建议将匹配器从最具体到最不特定的顺序重新排序,否则对api/items
的调用将由api/**
匹配器匹配,而不是api/items
匹配器匹配。
.antMatchers("/api/items", "api/items/").hasRole("USER")
.antMatchers("/api/**").hasRole("ADMIN")
答案 1 :(得分:1)
在@GetMapping
或@PostMapping
的顶部,您可以添加以下注释来管理基于角色的访问
@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
@PostMapping(value = "/api/addItem",consumes = {"application/json"},produces = {"application/json"})
@ResponseBody
public Item addItem(@RequestBody Item item) {
itemService.addItem(item);
return item;
}