Spring Boot: имитация аутентификации пользователя с контекстом безопасности с использованием Junit - PullRequest
1 голос
/ 20 июня 2020

Я хочу создать тест JUnit 5 для Rest API, который использует проверку токена JWT:

    @Test
    public void resetTokenTest_OK() throws Exception {
        when(userService.findByResetPasswordToken(anyString())).thenReturn(trueOptional);

        mockMvc.perform(post("/users/reset_token")
                .contentType(MediaType.APPLICATION_JSON)
                .content(ResetPasswordTokenDTO))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.resetPasswordToken").value(randomString_254))
                .andExpect(jsonPath("$.login").value("login"))
                .andExpect(jsonPath("$.status").value("200"))
                .andExpect(jsonPath("$.error").value(""))
                .andExpect(jsonPath("$.errorDescription").value(""));
    }

GitHub

Я делаю запрос Mockup, используя эту полезную нагрузку:

{
  "resetPasswordToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.VFb0qJ1LRg_4ujbZoRMXnVkUgiuKq5KxWqNdbKq_G9Vvz-S1zZa9LPxtHWKa64zDl2ofkT8F6jBt_K4riU-fPg",
  "login": "login",
  "status": "1",
  "error": "",
  "errorDescription": ""
}

Я получаю NPE для этой строки :

Caused by: java.lang.NullPointerException
    at org.engine.utils.GenericUtils.getLoggedInUser(GenericUtils.java:15)
    at org.engine.rest.UsersController.lambda$resetToken$0(UsersController.java:159)
    at java.base/java.util.Optional.map(Optional.java:258)
    at org.engine.rest.UsersController.resetToken(UsersController.java:153)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)

Full Log :

Я получаю NPE для этот код:

return (Users) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

GitHub

Как я могу имитировать результат от SecurityContextHolder.getContext().getAuthentication().getPrincipal(), чтобы не получить NPE?

1 Ответ

3 голосов
/ 20 июня 2020

Есть несколько способов имитировать безопасность, используя @WithMockUser, @WithAnonymousUser, @WithUserDetails, @WithSecurityContext. Вы можете использовать эти аннотации с @Test методом


@WithMockUser

  • Пользователь с именем пользователя "user" "не обязательно должно существовать, так как мы издеваемся над пользователем
  • Аутентификация, заполненная в SecurityContext, имеет тип UsernamePasswordAuthenticationToken
  • Принципал аутентификации - это объект User Spring Security.
  • Пользователь будет иметь имя пользователя «пользователь» , пароль «пароль» и один GrantedAuthority с именем «ROLE_USER» is используется.
  • Вы можете настроить такие параметры, как имя пользователя, роли, значение

@WithAnonymousUser

Использование @WithAnonymousUser позволяет работать как анонимный пользователь. Это особенно удобно, когда вы используете sh для запуска большинства тестов с определенным пользователем c, но хотите запустить несколько тестов от имени анонимного пользователя. Например, следующее будет работать сMockUser1 и withMockUser2 с использованием @WithMockUser и анонимно в качестве анонимного пользователя .


@WithUserDetails

Хотя @WithMockUser - очень удобный способ начать работу, он может не работать во всех случаях. Например, приложения обычно ожидают, что принципал Authentication будет иметь специфический c тип . Это сделано для того, чтобы приложение могло ссылаться на принципала как на настраиваемый тип и уменьшать связь в Spring Security.

Пользовательский принципал часто возвращается настраиваемым UserDetailsService, который возвращает объект, реализующий оба UserDetails и произвольного типа. В подобных ситуациях полезно создать тестового пользователя с помощью настраиваемой службы UserDetailsService. Это именно то, что делает @WithUserDetails.


@WithSecurityContext

Мы можем создать нашу собственную аннотацию, использующую @WithSecurityContext для создания любого SecurityContext, который мы хотим. Например, мы могли бы создать аннотацию с именем @WithMockCustomUser как @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)

...