Spring Repository PreAuthorize给出了“未能评估表达式”错误

时间:2017-10-04 14:29:35

标签: spring spring-security

我添加了许多大胆的内容,因为有人降级了我的问题,这个问题很奇怪......

我从这里开始工作,这意味着为@PreAuthorize正确配置了事情......

@RestController
@RequestMapping('/people')
public PersonController extends BaseController {
   @PreAuthorize("#pesonId != principal.id")
   @RequestMapping(value="updatePerson", method={RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
   public @ResponseBody SimpleResponseStatus updatePerson(@RequestParam(personId) final Long personId, @RequestParam(value) final String value, final HttpServerRequest request, final HttpServletResponse response)
   {
      Person p = personRepo.findById(personId);
      p.setValue(value);
      personRepo.save(p);
   }
}

并转移到无效的 ...存储库中的@PreAuthorize save()...

public interface PersonRepository extends JpaRepository<Person,Long> {

  @SuppressWarnings("unchecked")
  @Override
  @PreAuthorize("#p.id != principal.id")
  Person save(person p);

}

现在我得到了“无法评估表达式'#p.id!= principal.id'

它在Controller上运行时的一个区别是我做了#personId而不是#p.id所以我不知道表达式中的对象vs原语是问题还是Controller vs Repository(我在哪里做)评估)是问题。

所以我有几个问题......

  1. 我是否必须做一些特殊工作才能让PreAuthorize在存储库中工作?

  2. 与Spring安全无关,但为什么我被迫添加SuppressWarnings?我可以看看我是否正在回归List<Person>,但我觉得这很奇怪。

  3. 还有另一个例子,我想要做一个像“#p.group.id!= 3”这样的PreAuthorize表达式......评估中的等级是否有限制?即level = obj.obj.obj.obj.value

  4. 另一件有趣的事情是,当我使用Controller时,我不需要花括号“#{userId!= 3}”,但它与“#userId!= 3”一起工作,我从{获得了该语法{3}}

    底线,我让它在Controller中工作但没有对象参数,现在我需要它在Repository和object参数中工作。我已经尝试了#person.id!= 3以及#{person.id!= 3}并且都没有工作。

2 个答案:

答案 0 :(得分:-1)

你必须先:
- 启用全局方法安全性

在你的spring security配置中添加

@EnableGlobalMethodSecurity(prePostEnabled=true)

您可以安全地使用@PreAuthorize和@PostAuthorize

  • 正确的SPEL语法应为

    #{pesonId!= principal.id}

但是......在此之前你应该确保SPringEvaluationContext中都存在这两个参数。

我建议使用Spring方法,它不适合你的问题,但会给你一个不同的问题观点。

表达式访问控制的用法
https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

ex:@PreAuthorize("hasRole('ADMIN')")

Spring安全性接受注释中的任何有效Spel 看看这里:
http://www.baeldung.com/spring-security-expressions-basic

答案 1 :(得分:-1)

我找到了自己问题的答案:here

基本上对于Repository,您必须通过注释添加参数名称,因为调试未编译到接口中。

我花了很长时间才终于找到了答案,因为我尝试了不同的EL语法试用和错误,最后我选择的一种语法给了我一个不同的(更好的)错误信息,从那里我找到了上面的链接

无论如何,任何降级我的问题的人都应该刚刚发布了我刚刚上面提到的链接,而不是降级我。这只是意思,真的。

public interface PersonRepository extends JpaRepository<Person,Long> {

  @SuppressWarnings("unchecked")
  @Override
  @PreAuthorize("#p.id != principal.id")
  Person save(@Param("p") person p);  //the @Param annotation is needed!

}

同样,有趣的是我需要看到{}的某些地方,而其他地方则不需要。我不需要括号来工作。