簡體   English   中英

Spring Boot測試不遵守Web安全配置

[英]Spring boot test does not respect web security configuration

我正在為Rest API控制器編寫測試。 無需任何授權即可訪問此端點:

@EnableWebSecurity
@Configuration
@Import(AppConfig.class)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired 
private UserDetailsRepository accountRepository;

@Autowired
private CustomUserDetailsService customUserDetailsService;

@Autowired
private JWTAuthenticationFilter jwtAuthenticationFilter;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
        .authorizeRequests()
            .anyRequest().authenticated().and()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

/*
 * Apparently, permitAll() doesn't work for custom filters, therefore we ignore the signup and login endpoints 
 * here
 */
@Override
public void configure(WebSecurity web)
        throws Exception {
    web.ignoring()
        .antMatchers(HttpMethod.POST, "/login")
        .antMatchers(HttpMethod.POST, "/signup");
}

/*
 * set user details services and password encoder
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

/* Stopping spring from adding filter by default */
@Bean
public FilterRegistrationBean rolesAuthenticationFilterRegistrationDisable(JWTAuthenticationFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

}

JWTAuthenticationFilter類:

@Component
public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private UserDetailsService customUserDetailsService;

    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    private final static UrlPathHelper urlPathHelper = new UrlPathHelper();

    final static String defaultFilterProcessesUrl = "/**";

    public JWTAuthenticationFilter() {
        super(defaultFilterProcessesUrl);
        super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl)); //Authentication will only be initiated for the request url matching this pattern
        setAuthenticationManager(new NoOpAuthenticationManager());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication authentication = AuthenticationService.getAuthentication(request, customUserDetailsService);
        return getAuthenticationManager().authenticate(authentication);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        logger.debug("failed authentication while attempting to access "+ urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Authentication Failed");
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        SecurityContextHolder.getContext().setAuthentication(authResult);
        chain.doFilter(request, response);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        super.doFilter(req, res, chain);
    }
} 

當我請求(使用郵遞員)“注冊”端點時,它可以正常工作。 但是,當我運行測試時,由於未通過身份驗證,因此擊中了doFilter並失敗了。

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class AuthenticationControllerFTest {

    @Autowired 
    private MockMvc mockMvc;

    @MockBean
    private AuthenticationManager authenticationManager;

    @Test
    public void testCreate() throws Exception {
        Authentication authentication = Mockito.mock(Authentication.class);
        Mockito.when(authentication.getName()).thenReturn("DUMMY_USERNAME");
        Mockito.when(
                authenticationManager.authenticate(Mockito
                        .any(UsernamePasswordAuthenticationToken.class)))
                .thenReturn(authentication);

        String exampleUserInfo = "{\"name\":\"Test1234\",\"username\":\"test@test.com\",\"password\":\"Salam12345\"}";
        RequestBuilder requestBuilder = MockMvcRequestBuilders
                .post("/signup")
                .accept(MediaType.APPLICATION_JSON).content(exampleUserInfo)
                .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(requestBuilder).andReturn();

        MockHttpServletResponse response = result.getResponse();
        int status = response.getStatus();
        String content = response.getContentAsString();
        System.out.println(content);
        Assert.assertEquals("http response status is wrong", 200, status);
    }
}

關於如何解決此問題的任何想法嗎?

通過將以下代碼添加到測試類中,解決了該問題:

@Autowired
private WebApplicationContext context;

@Autowired
private Filter springSecurityFilterChain;

@Before
public void setup() {
    mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .addFilters(springSecurityFilterChain).build();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests()
            .antMatchers("/**").permitAll()
            .anyRequest().authenticated();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM