当前位置: 首页 > 知识库问答 >
问题:

SpringBootRest控制器集成测试总是给401未经授权

仉宸
2023-03-14

我有一个rest控制器,它有简单的CRUD操作。我正在尝试编写集成测试。

下面是我的RestController:

package com.gasx.corex.scheduler.controller;

import java.awt.*;
import java.util.List;

import com.gasx.corex.scheduler.service.SchedulerJobServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.scheduler.service.SchedulerJobService;


@RestController
@RequestMapping("/gasx/restscd")
public class SchedulerJobController {

    @Autowired
    private SchedulerJobServiceI schedulerJobService;

    @RequestMapping(method = RequestMethod.GET , path="/getschedulerjobs" , produces= MediaType.APPLICATION_JSON_VALUE)
    public List<SchedulerJob> getAllSchedulerJobs() {
        return schedulerJobService.getAllSchedulerJobs();
    }

    @RequestMapping(method = RequestMethod.POST, value = "/addschedulerjob")
    public void addSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.addSchedulerJob(schedulerJob);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/updateschedulerjob")
    public void updateSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.updateSchedulerJob(schedulerJob);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/deleteschedulerjob")
    public void deleteSchedulerJob(@RequestBody SchedulerJob schedulerJob) {
        schedulerJobService.deleteSchedulerJob(schedulerJob);
    }
}

我已经为RestController中的所有endpoint编写了集成测试

集成测试类:-

package com.gasx.corex.ext.scheduler.integrationtest.domain;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gasx.corex.base.configuration.CoreConfiguration;
import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.ext.scheduler.domain.utils.SchedulerJobType;


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import sun.security.krb5.internal.Ticket;
import org.springframework.http.HttpMethod;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

import java.io.IOException;
import java.util.Base64;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT  , properties = {
        "management.server.port=0", "management.context-path=/admin" ,"security.basic.enabled=false"} )
@EnableAutoConfiguration
@ContextConfiguration( classes = {CoreConfiguration.class  } )
@AutoConfigureMockMvc
public class SchedulerJobTestInt {

    @LocalServerPort
    private int port  ;


    @Autowired
    private TestRestTemplate testRestTemplate;

    @Autowired
    WebApplicationContext context;

    @Autowired
    private MockMvc mockMvc;


    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

    @Test
    public void getAllSchedulerJobsIntTest() throws Exception {
        ResponseEntity<String> response = testRestTemplate.getForEntity("http://localhost:" + port +"/gasx/restscd/getschedulerjobs", String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode responseJson = objectMapper.readTree(response.getBody());

        assertThat(responseJson.isMissingNode()).isFalse();
        assertThat(responseJson.toString()).isEqualTo("[]");
    }




    @Test
    public void addSchedulerJobIntTest() throws  Exception{
        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");






        String plainCredentials="gasx:gasx!";
        String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + base64Credentials);
        headers.add("Accept" , "application/json");


        HttpEntity<String> entity = new HttpEntity<String>(asJsonString(schedulerJob), headers);


        //    ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:"+port +"/gasx/restscd/addschedulerjob", entity,Void.class);
        ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:" + port +"/gasx/restscd/addschedulerjob", asJsonString(schedulerJob),Void.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

    }

    private String createURLWithPort(String uri) {
        return "http://localhost:" + port + uri;
    }

    @Test
    public void updateSchedulerJobTest(){
        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");

        ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/updateschedulerjob", schedulerJob,Void.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

    }

    @Test
    public void deleteSchedulerJob(){

        SchedulerJob schedulerJob = new SchedulerJob();
        schedulerJob.setName("ALB Cleanup");
        schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
        schedulerJob.setType(SchedulerJobType.REST);
        schedulerJob.setActive(true);
        schedulerJob.setStartMissedRun(false);
        schedulerJob.setCategory("SYSTEM");
        schedulerJob.setCronExpression(null);
        schedulerJob.setScheme("testScheme");
        schedulerJob.setIdRegion(1);
        schedulerJob.setAlbEndpoint("testAlbEndPoint");
        schedulerJob.setAlbPayload("SCHED_ALB");
        schedulerJob.setAlbPrio(1);
        schedulerJob.setAlbJobUser("MKRAUS");
        schedulerJob.setScriptParams("testScriptParams");
        schedulerJob.setShellScriptParams("clear_tmp 15");
        schedulerJob.setSoapEndpointAlias("");
        schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
        schedulerJob.setSoapExportPath("testExportPath");
        schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
        schedulerJob.setSoapAction("urn:readPartnersById");
        schedulerJob.setRestEndpointAlias("testEndpointAlias");
        schedulerJob.setRestUrl("testUrl");
        schedulerJob.setRestEntityContent("");
        schedulerJob.setRestExportPath("testRestExportPath");
        schedulerJob.setHookScriptName("testHookScriptName");
        schedulerJob.setMinutes("");
        schedulerJob.setHours("");

        ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/deleteschedulerjob", schedulerJob,Void.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);


    }


    public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

我的问题:

1.)当我把断点放在Rest控制器中时,它并没有停在那里,实际上它没有被调用。

2.)当我运行GET测试时,它会从响应返回登录html页面。getBody()

3.)当我运行POST测试时,它返回状态401 unauthorized

在谷歌上尝试了无数可能的解决方案,甚至通过评论配置来禁用Spring安全,但它仍然不起作用。

我可以从单元测试调用同一个Rest控制器,并可以停止断点。

我的安全配置:-

package com.gasx.corex.scheduler.server;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

import com.gasx.corex.ext.user.domain.DefaultRoles;

@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        // @formatter:off
        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .httpBasic().and()
            .authorizeRequests()
                .antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
                .antMatchers("/webjars/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
                .antMatchers("/monitor/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ACTUATOR.getName())
                // dev urls
                .antMatchers("/h2-console/**").hasAuthority(DefaultRoles.ROOT.getName())
                .antMatchers("/swagger*/**","/v2/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName())
                .anyRequest().denyAll();
        // @formatter:on

        httpSecurity.csrf().disable();
        httpSecurity.headers().frameOptions().disable();
    }
}

尝试了另一件事,将下面的类添加到我的包中:-

package com.gasx.corex.ext.scheduler.integrationtest.domain;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class AllowAnonymousWebAccess extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity web) throws Exception {
        web.antMatcher("**/*").anonymous();
    }
}

现在它给了404。

共有1个答案

濮丰
2023-03-14

我对这个项目的安全配置一无所知(你应该提供更多的信息),但是我认为你应该提供一些授权数据(比如授权头中的JWT)

你能给我更多关于SecurityConfig的信息吗?(查找org.springframework.security.config.something.something…imports)

编辑

我看了你的代码,实际上这部分

    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
        .httpBasic().and()
        .authorizeRequests()
            .antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())

正在使用httpBasic类型授权保护您的API。您应该在标头中提供凭据以测试应用程序。

 类似资料:
  • 在这个留档Spring Security MVC Test中描述了如何使用Spring Security测试安全的ressource。我遵循了提供的所有步骤,但访问受保护的ressource仍然会返回错误代码401(未经授权)。 这是我的测试课 我的资源服务器配置: 如果你想看看整个项目,你可以在这里找到。我已经尝试了不同的测试运行程序和教程中描述的所有内容,但我找不到一个解决方案,如何在测试期间

  • 我的代码:GoogleCredential凭据 credential.refreshToken() 错误日志: 创建服务号的步骤: 我在凭据中的oauth 2.0中创建了一个Web应用程序 然后我用客户端ID创建了一个服务号 现在我正在使用这个服务号和从它生成的p12证书来验证和创建Google凭据的对象 一旦刷新令牌,我就给了我401例外。 在这种情况下,任何帮助都会受到感激

  • 我想使用爪哇谷歌驱动器API。我尝试了这段代码: 但是我得到了这个错误: 我使用以下配置: 你能告诉我怎么解决这个问题吗?

  • null null 使用NodePort服务公开Keycloak。 应用程序使用istio入口网关公开。 Keycloak服务器版本:9.0.0。

  • 我是第一次使用谷歌API,我在尝试下载文件对象“下载Url”属性的文件时遇到问题。我当前正在使用“服务帐户”选项以及关联的服务帐户电子邮件和 P12 证书。 但是,URL返回“https://doc-08-68-docs.googleusercontent.com/docs/securesc/bteg36c1tifegg79l2ov17og25612tet/gk7kn52ahe4d0to7d6ht

  • 我正在尝试登录基于cloudflare服务器的网站。我使用cloudserver绕过了登录问题,但我的下一个停止点是当我试图发送get请求以访问一些登录后令牌时。 我的代码: 这返回401作为答案: 它的标题是 好的,我首先试着给一个auth。这样地 我再次得到相同的错误,401,但这次响应的头确实有一个www身份验证,我应该质询 根据我所读到的内容,它是基本的意味着我必须在我的头文件中添加一个像