如何为测试安全控制器方法提供带有附加字段的自定义userdetails?

quhf5bfb  于 2021-09-30  发布在  Java
关注(0)|答案(2)|浏览(269)

假设我有以下几点 @WebMvcTest@RestController 在spring引导应用程序(版本2.4.2)中。

// the test

@Test
@WithUserDetails
public void should_return_ok() throws Exception {
    mockMvc.perform(get("/api/products").andExpect(status().isOk());
}

// the controller

@GetMapping(path = "/api/products")
public ResponseEntity<List<Product>> getProducts(@AuthenticationPrincipal CustomUserDetails userDetails) {
    List<Product> products = productService.getProductsByUserId(userDetails.getUserId());
    return ResponseEntity.ok(products);
}

我还提供了一个 CustomUserDetails 类,该类添加了 userId .

@Getter
@Setter
public class CustomUserDetails extends User {

    private static final long serialVersionUID = 5540615754152379571L;

    private Long userId;

    public CustomUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        super(username, password, authorities);
    }

    public CustomUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
    }
}

我知道spring提供了 @WithUserDetails 注解以提供适当的测试对象。这也允许指定自定义用户名、密码等。但是我不知道如何提供 userId 这是必要的,以便控制器方法可以从 CustomUserDetails 对象

krcsximq

krcsximq1#

您可以在测试类中创建自己的自定义userdetails对象,并执行以下操作:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;

CustomUserDetails customUserDetails = new CustomUserDetails(...);

mockMvc.perform(get("/api/products").with(user(customUserDetails))).andExpect(status().isOk());
ac1kyiln

ac1kyiln2#

在你实施 UserDetailsService 您应该返回您的 UserDetails . 例如:

@Override
public UserDetails loadByUsername(String username) throws UsernameNotFoundException {
   User user = userRepository.findByUsername(username);

   if (user == null) {
       throw new UsernameNotFoundException("Username " + username + " not found");
   }

   CustomUserDetails customUserDetails = new CustomUserDetails(user);
   customUserDetails.setUserId(user.getUserId());
   return customUserDetails;
}

public class CustomUserDetails implements UserDetails {
    private final Long userId;
    private final User user;

    ...constructors
    ...getters and setters
}

在代码中,可以强制转换 Authentication 反对你的 CustomUserDetails .

CustomUserDetails customUserDetails = (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication();
Long userId = customUserDetails.getUserId();

相关问题