我正在尝试在Spring Boot中的服务方法上测试PreAuthorize
批注。我已经设法让它评估SPeL表达式,但是在引用自定义bean时失败。
我正在测试的服务方法:
@PreAuthorize("hasPermission(#eventId.id(), @eventTypePermission.target, @eventTypePermission.write())")
public EventTypeId retrieveEventTypeIdForEventId(EventId eventId) {
return null;
}
测试代码:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class TestConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorProxyTest());
return expressionHandler;
}
@Bean
public EventTypePermission permission() {
return new EventTypePermission();
}
}
@Component
@Slf4j
class PermissionEvaluatorProxyTest implements PermissionEvaluator {
@Autowired
public PermissionEvaluatorProxyTest() {
}
@Override
public boolean hasPermission(
Authentication authentication, Object targetType, Object permission) {
return true;
}
@Override
public boolean hasPermission(
Authentication authentication, Serializable targetId, String targetType, Object permission) {
return true;
}
}
@Import({TestConfig.class})
@RunWith(SpringRunner.class)
@SpringBootTest(classes={EventUpdater.class})
public class EventUpdaterTest {
@Autowired
private EventUpdater eventUpdater;
@MockBean
private EventRepository repository;
@MockBean
private EventTypePermission eventTypePermission;
@Before
public void setup() {
}
@Test
@WithMockUser(username="test")
public void test() {
eventUpdater.retrieveEventTypeIdForEventId(new EventId(UUID.randomUUID()));
}
}
错误是:
java.lang.IllegalArgumentException: Failed to evaluate expression 'hasPermission(#eventId.id(), @eventTypePermission.target, @eventTypePermission.write())'
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'eventTypePermission'
深入其中,因为SPeL表达式使用的bean解析器实例为null,因此失败。关于为什么可能会发生这种情况以及如何设置bean解析器以便能够返回EventTypePermission
实例的任何想法?
我也尝试将@SpringBootTest(classes={EventUpdater.class})
更改为@SpringBootTest(classes={EventUpdater.class, EventTypePermission.class})
,但是没有运气。
答案 0 :(得分:2)
通过在配置类上显式设置应用程序上下文使它起作用:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class TestConfig extends GlobalMethodSecurityConfiguration {
private ApplicationContext applicationContext;
@Autowired
public TestConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorProxyTest());
expressionHandler.setApplicationContext(applicationContext);
return expressionHandler;
}
}
还必须更新SpringTestClass
批注以包含EventTypePermission
:
@SpringBootTest(classes={EventUpdater.class, EventTypePermission.class})
,而不是在TestConfig
类中定义Bean。