У меня есть поток сброса пароля с 3 шагами: начать, продолжить, завершить sh. Как часть шага продолжения, текущему пользователю предоставляется временное право на изменение своего пароля. Однако, когда я пытаюсь проверить эти полномочия в тесте, объект аутентификации имеет значение null.
Мне интересно, как я могу проверить, что эти полномочия были предоставлены, как и ожидалось?
Конфигурация (извлечение ):
@Autowired
@Bean
public JdbcUserDetailsManager configureGlobal(AuthenticationManager authenticationManager,
AuthenticationManagerBuilder auth) throws Exception {
JdbcUserDetailsManagerConfigurer jdbcUserDetailsManagerConfigurer = auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.withDefaultSchema();
jdbcUserDetailsManagerConfigurer.withUser(User.withUsername("user1")
.password(passwordEncoder().encode("user1"))
.roles("USER"));
JdbcUserDetailsManager jdbcUserDetailsManager = jdbcUserDetailsManagerConfigurer.getUserDetailsService();
jdbcUserDetailsManager.setAuthenticationManager(authenticationManager);
return jdbcUserDetailsManager;
}
Контроллер:
@RestController
@RequestMapping("/users")
public class UserController {
private JdbcUserDetailsManager userDetailsManager;
private PasswordResetTokenRepository passwordResetTokenRepository;
public UserController(JdbcUserDetailsManager userDetailsManager,
PasswordResetTokenRepository passwordResetTokenRepository) {
this.userDetailsManager = userDetailsManager;
this.passwordResetTokenRepository = passwordResetTokenRepository;
}
@PostMapping("/password-reset/continue")
public ResponseEntity<Void> continePasswordReset(@RequestBody ContinuePasswordChangeDto continuePasswordChangeDto) {
String username = continuePasswordChangeDto.getUsername();
String token = continuePasswordChangeDto.getToken();
UserDetails userDetails = userDetailsManager.loadUserByUsername(username);
PasswordResetToken passwordResetToken = passwordResetTokenRepository.findByToken(token);
if (userDetails != null && !userDetails.isEnabled() &&
passwordResetToken.getToken().equals(token) && passwordResetToken.getExpiryDate().isAfter(LocalDateTime.now())) {
Authentication auth = new UsernamePasswordAuthenticationToken(
userDetails, null, Arrays.asList(
new SimpleGrantedAuthority("CHANGE_PASSWORD_PRIVILEGE"))); // verify this in test
SecurityContextHolder.getContext().setAuthentication(auth);
return ResponseEntity.noContent().build();
}
return ResponseEntity.badRequest().build();
}
}
Тест:
@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@DisplayName("UserController")
@Transactional
public class UserControllerTest {
private final String pathPrefix = "/users";
private MockMvc mvc;
private final WebApplicationContext webApplicationContext;
private PasswordResetTokenRepository passwordResetTokenRepository;
private RandomStringGenerationService randomStringGenerationService;
private ObjectMapper objectMapper;
private JdbcUserDetailsManager jdbcUserDetailsManager;
public UserControllerTest(MockMvc mvc, WebApplicationContext webApplicationContext,
PasswordResetTokenRepository passwordResetTokenRepository,
RandomStringGenerationService randomStringGenerationService,
JdbcUserDetailsManager jdbcUserDetailsManager,
ObjectMapper objectMapper) {
this.mvc = mvc;
this.webApplicationContext = webApplicationContext;
this.passwordResetTokenRepository = passwordResetTokenRepository;
this.randomStringGenerationService = randomStringGenerationService;
this.jdbcUserDetailsManager = jdbcUserDetailsManager;
this.objectMapper = objectMapper;
}
@BeforeEach
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
}
@DisplayName("A guest who has an account but isn't logged in can continue a password reset")
@Test
public void givenGuestWithAccount_whenPasswordResetContinued_thenAuthorityIsGranted() throws Exception {
String username = "user1";
String token = randomStringGenerationService.getRandomString();
PasswordResetToken passwordResetToken = new PasswordResetToken(username, token);
passwordResetTokenRepository.save(passwordResetToken);
UserDetails user = jdbcUserDetailsManager.loadUserByUsername(username);
UserDetails updated = User.withUserDetails(user).disabled(true).build();
jdbcUserDetailsManager.updateUser(updated);
// Continue the reset
ContinuePasswordChangeDto continuePasswordChangeDto = new ContinuePasswordChangeDto(username, token);
String jsonOfDto = objectMapper.writeValueAsString(continuePasswordChangeDto);
mvc.perform(post(pathPrefix + "/password-reset/continue")
.contentType(MediaType.APPLICATION_JSON)
.content(jsonOfDto)
.with(csrf())
).andExpect(status().isNoContent());
// This isn't working as there seem to be several SecurityContexts and this particular one has null auth :(
assertThat(SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(
new SimpleGrantedAuthority("CHANGE_PASSWORD_PRIVILEGE"))).isTrue();
}
}
Если я избавлюсь от части apply(springSecurity())
настройки теста, тест преуспевает ...