Spring mvc org.springframework.security.core.userdetails.User不能强制转换为MyUserDetails(Junit 5)
我正在使用JUnit5测试web应用程序,除了 SecurityContextHolder.getContext().getAuthentication().getPrincipal() 运行测试用例时控制器类中的行位于 org.springframework.security.core.userdetails.User而不是MyUserDetails(在spring引导中运行应用程序时,返回对象是MyUserDetails,代码运行良好) 我的测试用例类Spring mvc org.springframework.security.core.userdetails.User不能强制转换为MyUserDetails(Junit 5),spring-mvc,spring-boot,junit,spring-security,junit5,Spring Mvc,Spring Boot,Junit,Spring Security,Junit5,我正在使用JUnit5测试web应用程序,除了 SecurityContextHolder.getContext().getAuthentication().getPrincipal() 运行测试用例时控制器类中的行位于 org.springframework.security.core.userdetails.User而不是MyUserDetails(在spring引导中运行应用程序时,返回对象是MyUserDetails,代码运行良好) 我的测试用例类 @ExtendWith(SpringE
@ExtendWith(SpringExtension.class)
@WebMvcTest(VendorController.class)
@AutoConfigureMockMvc
class VendorControllerTest {
@Autowired
private MockMvc mvc;
@Test
void test() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/vendor/user/getVendorList").with(csrf().asHeader())
.param("iDisplayStart","0")
.param("iDisplayLength", "10")
.param("iSortCol_0", "0")
.param("sSortDir_0", "asc")
.param("sSearch","")
.with(user("username").password("password").roles("2"))).andExpect(status().isOk());
}
}
在使用Junit 5运行测试用例时,返回org.springframework.security.core.userdetails.User对象,但如果通过spring boot运行项目,则返回的代码会正常工作
添加用户详细信息服务实施代码
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserSvc userSvc;
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
com.esociety.entity.UserEntity userEntity = userSvc.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(userEntity.getUserType());
return buildUserForAuthentication(userEntity, authorities);
}
private User buildUserForAuthentication(com.esociety.entity.UserEntity userEntity, List<GrantedAuthority> authorities) {
MyUserDetails myUserDetails = new MyUserDetails (userEntity.getUsername(), userEntity.getPassword(), userEntity.isEnabled(), userEntity.isAccountNonExpired(), userEntity.isCredentialsNonExpired(),userEntity.isAccountNonLocked(),authorities,userEntity.getUserId(),userEntity.getSocietyId(),userEntity.getUserType(),userEntity.getFirstName(),userEntity.getMiddleName(),userEntity.getLastName());
return myUserDetails;
}
private List<GrantedAuthority> buildUserAuthority(String userType) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
setAuths.add(new SimpleGrantedAuthority(userType));
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
@Service(“userdetailssservice”)
公共类MyUserDetailsService实现UserDetailsService{
@自动连线
私有用户svc UserSvc;
@事务(只读=真)
@凌驾
public UserDetails loadUserByUsername(最终字符串用户名)引发UsernameNotFoundException{
com.esocciety.entity.UserEntity UserEntity=userSvc.findByUserName(用户名);
列表权限=buildUserAuthority(userEntity.getUserType());
返回buildUserForAuthentication(用户实体、权限);
}
私人用户buildUserForAuthentication(com.esocciety.entity.UserEntity,列出权限){
MyUserDetails MyUserDetails=新建MyUserDetails(userEntity.getUsername(),userEntity.getPassword(),userEntity.isEnabled(),userEntity.IsAccountNoneExpired(),userEntity.isCredentialsNonExpired(),userEntity.isAccountNonLocked(),Authority,userEntity.getUserId(),userEntity.getUserType(),userEntity.getFirstName(),userEntity.getMiddleName(),userEntity.getLastName());
返回myUserDetails;
}
私有列表buildUserAuthority(字符串用户类型){
Set setAuths=new HashSet();
//建立用户权限
添加(新的SimpleGrantedAuthority(userType));
列表结果=新的ArrayList(setAuths);
返回结果;
}
}
MyUserDetails类
公共类MyUserDetails扩展了用户{
公共MyUserDetails(字符串用户名、字符串密码、启用布尔值、,
boolean AccountNoExpired,boolean CredentialsNoExpired,
布尔帐户未锁定,
集合问题在于您使用的是SecurityMockMvcRequestPostProcessors.user(字符串用户名)
RequestPostProcessor
将创建并返回一个org.springframework.security.core.userdetails.User
,它是userdetails
的一个实现,但不是您想要的MyUserDetails
相反,您可以使用SecurityMockMvcRequestPostProcessors.user(UserDetails用户)
,它允许您提交自己想要的UserDetails
的实现
更改您的测试,如下所示:
@Test
void test() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/vendor/user/getVendorList").with(csrf().asHeader())
.param("iDisplayStart","0")
.param("iDisplayLength", "10")
.param("iSortCol_0", "0")
.param("sSortDir_0", "asc")
.param("sSearch","")
.with(user(new MyUserDetails ("username", "password", true, true, true,true, Arrays.asList(new SimpleGrantedAuthority("2")),1,1,USER_TYPE,"FirstName","MiddleName","LastName")))).andExpect(status().isOk());
}
Reference Spring Security您是否使用UserDetailsService
的实现返回MyUserDetails
?如果是,您如何使该服务可用于测试(因为您没有加载整个Spring应用程序上下文)?@AndreiDamian Fekete我已经添加了UserDetails服务实现代码。当我登录到应用程序时,会调用buildUserForAuthentication方法,它会创建一个MyUserDetails对象来扩展用户,但我相信如果在Junit测试时调用一些buildUserForAuthentication方法,那么我将不会得到类转换Option issue.its表示将参数1强制转换为RequestPostProcessor,或让MyUserDetails实现RequestPostProcessor。使用((RequestPostProcessor)新的MyUserDetails(“用户名”、“密码”、true、true、true、true、true、true、Array.asList(新的SimpleGrantedAuthority(“2”)、2L、1L、“角色\ 2”、“名字”、“中间名”、“姓氏”))和Expect(status().isOk());
我仍然收到相同的错误您不能将MyUserDetails强制转换为RequestPostProcessor。您的代码更改是否运行?如果我不强制转换,它会给出编译错误,是的,代码正确运行代码中的几次更改,并且工作正常。。使用(user)(新的MyUserDetails(“用户名”,“密码”),true,true,true,true,Arrays.asList(新的SimpleGrantedAuthority(“2”)、2L、1L、“ROLE_2”、“Firstname”、“middlename”、“Lastname”))和Expect(status().isOk());
reference
@Test
void test() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/vendor/user/getVendorList").with(csrf().asHeader())
.param("iDisplayStart","0")
.param("iDisplayLength", "10")
.param("iSortCol_0", "0")
.param("sSortDir_0", "asc")
.param("sSearch","")
.with(user(new MyUserDetails ("username", "password", true, true, true,true, Arrays.asList(new SimpleGrantedAuthority("2")),1,1,USER_TYPE,"FirstName","MiddleName","LastName")))).andExpect(status().isOk());
}