Spring - SpEL在@PreAuthorize(" hasPermission")中将实体参数计算为空引用 [英] Spring - SpEL evaluates entity argument as null reference in @PreAuthorize("hasPermission")

查看:3919
本文介绍了Spring - SpEL在@PreAuthorize(" hasPermission")中将实体参数计算为空引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的问题是SpEL在此存储库的第二个方法中将实体参数作为空引用进行评估。第一种方法效果很好,id应该正确评估为Long。

I've got problem that SpEL is evaluating entity argument as null reference in the second method of this repository. This first method works well and id is correctly evaluated to Long as should be.

@NoRepositoryBean
public interface SecuredPagingAndSortingRepository<T extends AuditedEntity, ID extends Serializable>
        extends PagingAndSortingRepository<T, ID> {

    @Override
    @RestResource(exported = false)
    @PreAuthorize("hasPermission(#id, null, 'owner')")
    void delete(ID id);

    @Override
    @PreAuthorize("hasPermission(#entity, 'owner')")
    void delete(T entity);
}

这是我的自定义PermissionEvaluator:

This is my custom PermissionEvaluator:

@Slf4j
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    private final PermissionResolverFactory permissionResolverFactory;

    @Autowired
    public CustomPermissionEvaluator(PermissionResolverFactory permissionResolverFactory) {
        this.permissionResolverFactory = permissionResolverFactory;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        Assert.notNull(userDetails, "User details cannot be null");
        Assert.notNull(targetDomainObject, "Target object cannot be null");
        log.debug("Permmission: " + permission + " check on: " + targetDomainObject + " for user: " + userDetails.getUsername());

        PermissionType permissionType = PermissionType.valueOf(((String) permission).toUpperCase());
        return permissionResolverFactory.getPermissionResolver(permissionType).resolve(targetDomainObject.getClass(), authentication, (AuditedEntity) targetDomainObject);
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // TODO
        return false;
    }
}

由于断言该目标,此测试未通过在CustomPermissionEvaluator中,object不能为null。

This test doesn't pass because of assert that target object cannot be null in CustomPermissionEvaluator.

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@ContextConfiguration(classes = SqapApiApplication.class)
public class PermissionsIT {
    @Autowired
    private TestGroupRepository testGroupRepository;

    @Autowired
    private UserRepository userRepository;

    UserEntity user;

    @Before
    public void before() {
        user = new UserEntity("user", "password1", true, Sets.newHashSet(RoleType.ROLE_USER));
        user = userRepository.save(user);
    }

    @Test
    @WithMockUser(username="user")
    public void shouldDeleteWhenIsOwner() throws Exception {
        TestGroupEntity testGroupEntity = new TestGroupEntity("testGroup", "testdesc", Sets.newHashSet(new AbxTestEntity(1, "abx", "desc", null)));
        user.addTestGroup(testGroupEntity);
        user = userRepository.save(user);
        TestGroupEntity createdEntity = testGroupRepository.findAll().iterator().next();
        testGroupRepository.delete(createdEntity);
    }
}


推荐答案

接口中的spel引用方法参数,需要使用Spring Data的 @Param 对它们进行注释,以明确命名它们:

When referencing method parameters from spel in interfaces it pays to annotate them with Spring Data's @Param to explicitly name them:

@PreAuthorize("hasPermission(#entity, 'owner')")
void delete(@Param("entity") T entity);

如果参数未注释,Spring必须使用反射来发现参数名称。这只适用于接口方法,如果

If the parameters aren't annotated Spring has to use reflection to discover the parameter names. This is only possible for interface methods if


  • 你正在运行Spring 4 +

  • 你'重新运行Java 8

  • 接口是用JDK 8编译的,并指定了 -parameters 标志

  • You're running Spring 4+
  • You're running Java 8
  • The interface was compiled with JDK 8 and the -parameters flag was specified

对于类方法,Spring有另一个选项 - 它可以使用调试信息。这适用于Spring 3和早期版本的Java,但它又依赖于编译时标志来工作(即 -g )。

For class methods Spring has another option—it can use debug information. This works in Spring 3 and earlier versions of Java, but again it relies on a compile time flag to work (i.e. -g).

为了便于携带,最好注释你需要引用的所有参数。

For portability it's better to annotate all the parameters you need to reference.

参考:使用@PreAuthorize和@PostAuthorize进行访问控制

这篇关于Spring - SpEL在@PreAuthorize(&quot; hasPermission&quot;)中将实体参数计算为空引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆