我正在关注这个问题:
How to configure Spring Boot Security so that a user is only allowed to update their own profile
想象一下,我有一个端点void
,如果用户尝试编辑它们自己(例如:ID为1的用户正在访问/user/edit/{id}
但不能访问),我希望可以访问该端点/user/edit/1
)或(如果他们是管理员),以便能够编辑任何用户。
在安全配置中有什么方法可以实现这一目标?
user/edit/2
将其限制为管理员用户,我需要管理员或与用户ID匹配的ID。
我唯一能想到的就是控制器内部有类似的东西
.antMatchers("/user/edit/**").hasRole("ADMIN")
但是我给人的印象是我们不应该在控制器中对访问逻辑进行编码?
答案 0 :(得分:1)
要控制控制器中的角色访问,可以使用@Secured或@PreAuthorize之类的注释。
要使用@Secured,请在您的安全配置类中添加
:@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
现在您可以在控制器中使用它:
@Secured("ROLE_ADMIN")
@PostMapping
public Account post(Account account, double amount){
// ...
}
要使用@PreAuthorize,请在您的安全配置类中添加:
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
// ...
}
现在您可以在控制器中使用它:
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@PostMapping
public Account post(Account account, double amount){
// ...
}
有关更多信息,您可以check here Spring文档。
答案 1 :(得分:1)
可以使用Spring Security的Method Security Expressions来做到这一点。从文档复制的示例:
@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);
请阅读前面的部分,因为需要一些配置。另外请注意,如果重复使用表达式you can define your own security annotations。
给我的印象是,我们不应该在访问代码中对访问逻辑进行编码 控制器?
恕我直言,“应该”这个词太强了。安全表达式功能强大,从理论上讲,您可以将所有安全检查与控制器逻辑分开。支票有误或遗失时更容易发现。如果要使用Swagger注释来记录端点,则也更容易与Swagger注释进行比较。
但是当您必须执行诸如返回过滤器行之类的操作时,它可能会变得更加棘手,这样用户只能看到某些结果。 Spring Security可以使用@PostFilter来做到这一点。但是有时它不是最佳的。例如,如果您知道某些行将不会返回,则可以运行一个更快的查询,而不是事后过滤掉行。
我的第一个Spring Security项目有这样的查询,所以自从我倾向于使用控制器逻辑而不是安全注释。但这不是从不使用批注的充分理由!因此,在可能的情况下,请务必使用安全性表达式,但是,如果您对它们有疑问或有其他考虑,则将安全性与控制器逻辑集成起来并不是一件容易的事。