Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户

Posted

技术标签:

【中文标题】Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户【英文标题】:Spring Security, JUnit: @WithUserDetails for user created in @Before 【发布时间】:2017-07-16 22:57:53 【问题描述】:

在使用 Spring MockMVC 的 JUnit 测试中,有两种方法可以作为 Spring Security 用户进行身份验证:@WithMockUser 使用提供的凭据创建一个虚拟用户,@WithUserDetails 获取用户名并将其解析为正确的自定义 @987654324使用自定义UserDetailsServiceUserDetailsServiceImpl)实现@。

就我而言,UserDetailsService 从数据库加载用户。我要使用的用户已插入到测试套件的@Before 方法中。

但是,我的UserDetailsServiceImpl 找不到用户。

在我的@Before 中,我这样插入用户:

User u = new User();
u.setEMail("test@test.de");
u = userRepository.save(u);

UserDetailsServiceImpl:

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
    User user = this.userRepository.findOneByEMail(username);

    if (user == null)
        throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
    return user;

如何将@Before 中创建的帐户与@WithUserDetails 一起使用?

【问题讨论】:

这个 *** 的答案很有启发性:Spring Test & Security: How to mock authentication? 【参考方案1】:

使用setupBefore = TEST_EXECUTION

这将有效地导致@WithUserDetails@Before@BeforeEach 之后执行

@BeforeEach
public void createUser() 
   ...


@Test
@WithUserDetails(value = "username", setupBefore = TestExecutionEvent.TEST_EXECUTION)
public void expectToWork() 
   ...

【讨论】:

【参考方案2】:

您可以使用@PostConstruct 代替@Before。这对我有用。有人可以确认吗?

【讨论】:

这工作正常。任何人都知道任何副作用,到目前为止我没有看到...?【参考方案3】:

不幸的是,@WithUserDetails@Before 不能轻易做到,因为 Spring @WithUserDetails 注释会在运行 setUp 方法和 @Before 之前调用 Spring 安全上下文测试侦听器。

这里是https://***.com/a/38282258/1814524 的一个小技巧并回答您的问题。

【讨论】:

注意:如果您使用事务,则需要手动删除 @AfterTransaction 的内容。它们不会像 @Before 那样自动回滚。 2021 更新:setupBefore = TEST_EXECUTION 对我有用。看我的回答。【参考方案4】:
@Inject
private EntityManager em;

@Inject
PlatformTransactionManager txManager;

@BeforeTransaction
public void setup() 
    new TransactionTemplate(txManager).execute(status -> 

        User u = new User();
        u.setEMail("test@test.de");
        em.save(u);

        return null;
    );


@AfterTransaction
public void cleanup() 
    new TransactionTemplate(txManager).execute(status -> 
        // Check if the entity is managed by EntityManager.
        // If not, make it managed with merge() and remove it.
        em.remove(em.contains(u) ? user1 : em.merge(u));
        return null;
    );



@Test
@Transactional
@WithUserDetails(value = "test@test.de", userDetailsServiceBeanName = "loadUserByUsername")
public void test() 


【讨论】:

以上是关于Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户的主要内容,如果未能解决你的问题,请参考以下文章

JUnit 4 & Spring Boot - 在测试前有选择地重新加载上下文/重新加载 Spring Security 配置

在Junit 5测试中注入Spring数据存储库

Spring Boot junit测试安全应用程序

Spring Boot junit 测试安全应用程序

如何使用 Spring Security 管理 Spring Boot 中的会话?

org.springframework.security.core.userdetails.User 不能转换为 MyUserDetails (Junit 5)