Error creating bean with name ‘securityConfiguration’

huangapple go评论83阅读模式
英文:

@WebMvcTest Error creating bean with name 'securityConfiguration'

问题

这里是您提供的翻译内容:

我有一个使用Spring Boot的REST应用程序,我在其中使用JWT进行身份验证,当我只启动应用程序时,它能正常运行。

我只是想添加一些测试案例,但我无法解决这个问题(我使用 mvn test 运行测试案例):

错误表明Spring无法创建userDetailsService bean,但这似乎是不正确的,因为我的应用程序可以毫无问题地运行。

注意:我尝试通过 @MockBean 添加 userdetailservice 的模拟。但这次Spring对于 MyAuthenticationEntryPoint 显示相同的错误。我认为应该有一个解决方案可以自动添加所有配置,或者避免对此端点进行全部配置。

[ERROR] verifyRegisterUserHttpRequest  Time elapsed: 0.008 s  <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'securityConfiguration': Unsatisfied dependency expressed 
through field 'userDetailsService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'com.myProjects.sample.security.MyUserDetailsService' available: expected at least 1 bean which qualifies as autowire candidate. 
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
  • 这是测试类:
package com.myProjects.sample.controller;

@WebMvcTest(controllers = RegisterController.class)
public class RegisterControllerTest {
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;
    @MockBean
    private RegisterService registerService;
    @MockBean
    private ValidationService validationService;

    // 1. 验证 Http 请求匹配
    @Test
    public void verifyRegisterUserHttpRequest() throws Exception {
        NewCustomerRequest requestBody = new NewCustomerRequest();
        requestBody.setEmailAddress("sample@sample.com");
        requestBody.setPhoneNumber("01112223344");
        requestBody.setPassword("password");
        requestBody.setPasswordVerify("password");

        mockMvc.perform(post(MyWebUrls.API.API + MyWebUrls.Register.REGISTER_USER)
                .content(objectMapper.writeValueAsString(requestBody))
                .contentType("application/json"))
                .andExpect(status().isOk());
    }
}
  • RegisterController 和 SecurityConfiguration
package com.myProjects.sample.controller;
@RestController
@RequestMapping(MyWebUrls.API.API)
public class RegisterController {

    @Autowired
    private RegisterService registerService;

    @Autowired
    private ValidationService validationService;

    @PostMapping(MyWebUrls.Register.REGISTER_USER)
    public ResponseEntity<?> registerUser(@Valid @RequestBody NewCustomerRequest newCustomerRequest, BindingResult bindingResult){
        String validationResultMessage = validationService.getFirstValidationErrorMessage(bindingResult);
        // ...
    }
}
package com.myProjects.sample.security;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private MyAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private CustomAccessDeniedHandler accessDeniedHandler;

    @Bean
    public AuthTokenFilter authJwtTokenFilter(){
        return new AuthTokenFilter();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    // ....
  • 还要查看我的自定义详情服务类
package com.myProjects.sample.security;
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String emailOrMobilePhone) throws UsernameNotFoundException {
        // ...
    }
}
英文:

I have a spring boot rest application where I use JWT for authentication and it works fine when I just start the application.

I just wanted to add some test cases but I could not solve this problem (I run the test cases with mvn test :

> Error states that Spring can not create userDetailsService bean but this seems incorrect, because my application can run without any issue.

Not: I have tried to add userdetailservice mock via @MockBean. But this time spring shows the same error for MyAuthenticationEntryPoint. I think there should be a solution to add all configuration automatically, or avoid them all for this endpoint.

[ERROR] verifyRegisterUserHttpRequest  Time elapsed: 0.008 s  &lt;&lt;&lt; ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name &#39;securityConfiguration&#39;: Unsatisfied dependency expressed 
through field &#39;userDetailsService&#39;; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type &#39;com.myProjects.sample.security.MyUserDetailsService&#39; available: expected at least 1 bean which qualifies as autowire candidate. 
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
  • Here is the test class:
package com.myProjects.sample.controller;

@WebMvcTest(controllers = RegisterController.class)
public class RegisterControllerTest {
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;
    @MockBean
    private RegisterService registerService;
    @MockBean
    private ValidationService validationService;

    // 1. Verifying Http Request Matching
    @Test
    public void verifyRegisterUserHttpRequest() throws Exception {
        NewCustomerRequest requestBody = new NewCustomerRequest();
        requestBody.setEmailAddress(&quot;sample@sample.com&quot;);
        requestBody.setPhoneNumber(&quot;01112223344&quot;);
        requestBody.setPassword(&quot;password&quot;);
        requestBody.setPasswordVerify(&quot;password&quot;);

        mockMvc.perform(post(MyWebUrls.API.API + MyWebUrls.Register.REGISTER_USER)
                .content(objectMapper.writeValueAsString(requestBody))
                .contentType(&quot;application/json&quot;))
                .andExpect(status().isOk());
    }
}
  • RegisterController and SecurityConfiguration
package com.myProjects.sample.controller;
@RestController
@RequestMapping(MyWebUrls.API.API)
public class RegisterController {

    @Autowired
    private RegisterService registerService;

    @Autowired
    private ValidationService validationService;

    @PostMapping(MyWebUrls.Register.REGISTER_USER)
    public ResponseEntity&lt;?&gt; registerUser(@Valid @RequestBody NewCustomerRequest newCustomerRequest, BindingResult bindingResult){
        String validationResultMessage = validationService.getFirstValidationErrorMessage(bindingResult);
		// ...
        }
    }
}
package com.myProjects.sample.security;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private MyAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private CustomAccessDeniedHandler accessDeniedHandler;

    @Bean
    public AuthTokenFilter authJwtTokenFilter(){
        return new AuthTokenFilter();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    // ....
  • And also see my custom details service class
package com.myProjects.sample.security;
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String emailOrMobilePhone) throws UsernameNotFoundException {
        // ...
    }
}

答案1

得分: 1

以下是翻译好的内容:

你能将以下依赖项添加到你的项目中吗?

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>

这样应该可以确保为你的 @WebMvcTest 配置也填充了安全性配置。

然后,你可以使用多种技术来模拟在使用 MockMvc 访问你的应用程序时的凭据/用户:

@Test
@WithMockUser("duke")

或者

@Test
public void testWithSecurityMockMvcRequestPostProcessors() throws Exception {
  this.mockMvc
    .perform(
      post("/your/endpoint")
        .with(jwt())
        .with(csrf())
    )
    .andExpect(status().isOk());

}

有关 MockMvc 和 Spring Security 集成的更多信息可以在 这里 找到。

英文:

Can you add the following dependency to your project?

&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
  &lt;artifactId&gt;spring-security-test&lt;/artifactId&gt;
  &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

This should then ensure to also populate your security configuration for your @WebMvcTest.

You can then use several techniques to mock credentials/user when accessing your application with MockMvc:

@Test
@WithMockUser(&quot;duke&quot;)

or

@Test
public void testWithSecurityMockMvcRequestPostProcessors() throws Exception {
  this.mockMvc
    .perform(
      post(&quot;/your/endpoint&quot;)
        .with(jwt())
        .with(csrf())
    )
    .andExpect(status().isOk());

}

More information for the MockMvc and Spring Security integration can be found here.

huangapple
  • 本文由 发表于 2020年9月5日 23:50:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63755795.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定