我使用Spring-data-rest暴露了一些实体,我想使用Spring表达式语言配置访问控制并进行预授权,以便用户只能操作属于他的实体。
我的主要对象在其用户名(String)中包含用户ID,用户具有属性id(Long):
module.exports = app => {
app.post("/signup", authentication.signup);
// No () here ---------------------------^
};
我的存储库看起来像这样:
@Entity
@Table(name = "users")
@Getter
@Setter
public class User {
@Id
@Column(name = "user_id", nullable = false, updatable = false)
private Long id;
...
}
但是,当在身份验证为@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Override
@PreAuthorize("hasRole('ROLE_ADMIN')")
User findOne(Long id);
@Override
@PreAuthorize("#user.id == principal.username")
void delete(User user);
...
}
(主体在其用户名中包含此ID)的用户进行身份验证时调用DELETE /users/1
时,我会收到以下异常:
1
我的表达基于官方Spring documentation。有人能指出我在这里缺少什么吗?
编辑: 我在我的存储库中添加了所有方法,因为它们似乎是互连的。
答案 0 :(得分:0)
在您的课程User
中,您必须注意id
是private
所以,您的代码应该调用公共方法来获取用户ID,所以它必须是这样的:
@Override
@PreAuthorize("#user.getId() == authentication.getName()")
void delete(@RequestParam(name="user", required=true)User user);
.....
您还必须调用公共方法以从主体获取用户名。
另外,请注意您可以调用安全检查功能来执行更多逻辑,例如:
@Autowired
private SecurityCheck securityCheck;
................
@Override
@PreAuthorize("@securityCheck.check(#user,authentication)")
void delete(User user);
在SecurityCheck类中可以这样定义:
@Component
public class SecurityCheck {
public boolean check(User user, Authentication authentication) {
if(user == null)
return false;
if(user.getId().equals(authentication.getName()))
return true;
// more logic ...
return false;
}
}