mardi 23 juillet 2019

How to test SpringSecurity expression based access control. EL expression unable to find bean

I have simple SpringBoot application that uses Spring Security. Access control works correctly under runtime, but it fails when testing. I get following errors:

java.lang.IllegalArgumentException: Failed to evaluate expression '@userSecurity.hasUserId(authentication,#userId)'

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1058E: A problem occurred when trying to resolve bean 'userSecurity':'Could not resolve bean reference against BeanFactory'

It simply checks if userId provided in Url matches currently logged user via expression

...
  .antMatchers("/**/user/{userId}/**/")
                    .access("@userSecurity.hasUserId(authentication,#userId)")
...

created a bean responsible for User id value check:

@Component
public class UserSecurity {

    public boolean hasUserId(Authentication authentication, Long userId) {    
        Object principalRaw = authentication.getPrincipal();
        User loggedUser;
        if (principalRaw instanceof User) {
            loggedUser = (User) principalRaw;
            if (loggedUser.getId() == userId) {
                return true;
            }
        }
        return false;
    }
}

Finally the test that causes error:

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = StockController.class)
@Import({WebMvcConfig.class, UserSecurity.class})
public class StockControllerTest {
@Autowired
MockMvc mockMvc;

//autowired correctly (Bean exists in Context)
@Autowired
UserSecurity userSecurity;

@Test
@WithMockUser("mockUser")
public void TestControllerSecret() throws Exception {
    mockMvc.perform(get("/test/user/1")).andExpect(status().isOk());
}

As You can see I have injected UserSecurity bean just for test purpose, to check if bean exists in Spring Context. I was wondering if @WebMvcTest annotation prevents bean from being created but clearly it doesn't. Bean injects correctly.

Somehow spEL in security access check does not recognize it and throws errors mentioned above.

Aucun commentaire:

Enregistrer un commentaire