REST 请求在“@SpringBootTest”中执行时被阻止,但在我运行应用程序时却未被阻止?

2024-03-26

我有一个带有 Jersey REST api 的 Spring Boot 应用程序,位于/rest:

@Component
@ApplicationPath("/rest")
public class RestApplication extends ResourceConfig {
    public RestApplication(){
        packages("ch.cypherk.myapp.service.rest");
    }
}

这是应该允许用户登录的控制器:

@Service
@Path("/login")
class LoginRestController
@Inject constructor(
    private val authenticationService: MyAuthenticationProvider
) {

    @Operation(summary = "Login user, use cookie JSESSIONID in response header for further requests authentication.",
        requestBody = RequestBody(description = "Login credentials of user.", required = true,
            content = [Content(schema = Schema(implementation = LoginDto::class))]),
        responses = [
            ApiResponse(responseCode = "202", description = "Login successful."),
            ApiResponse(responseCode = "403", description = "Invalid credentials supplied.")])
    @POST
    fun postLogin(loginCredentials: LoginDto) {
        val auth = UsernamePasswordAuthenticationToken(loginCredentials.username,loginCredentials.password)
        authenticationService.authenticate(auth)
    }
}

Where

@Service
class MyAuthenticationProvider (
    ...
): AbstractUserDetailsAuthenticationProvider() {

    @Transactional
    override fun authenticate(authentication: Authentication?): Authentication {
        return super.authenticate(authentication)
    }
    ...
}

只是一个添加了一堆额外检查的自定义实现。

如果我启动 Spring Boot 应用程序并使用邮递员向http://localhost:8080/rest/login有了有效的凭据,一切都会按预期进行。

但是,如果我尝试为其编写一个测试,

import com.mashape.unirest.http.Unirest
import io.restassured.RestAssured.given
import org.apache.http.HttpStatus.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner

@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
class LoginRestControllerIT {

    @Test
    fun login() {
        given()
            .contentType("application/json")
            .body(LoginDto("testuserA", "secret"))
        .When()
            .post("/rest/login")

        .then()
            .statusCode(SC_NO_CONTENT)
            .cookie("JSESSIONID")
    }
}

它给了我一个错误,因为我期望204(无内容)响应代码并得到403(禁止)。

Why?

上面的代码是使用放心 http://rest-assured.io/,但问题不是由于框架造成的,因为我尝试用以下方法重写测试Unirest http://unirest.io/,

val response = Unirest.post("http://localhost:8080/rest/login")
    .field("username","testuserA")
    .field("password","secret")
    .asJson()

assertThat(response.status).isEqualTo(SC_NO_CONTENT)

并得到同样的错误。

我在我的第一个语句处设置了一个断点LoginRestController's login功能,但未达到。这意味着链中较早的某个地方已经拒绝了请求

我的安全配置如下所示:

@Configuration
@EnableWebSecurity
@EnableVaadin
@EnableVaadinSharedSecurity
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    prePostEnabled = true,
    proxyTargetClass = true
)
class VaadinAwareSecurityConfiguration @Inject constructor(
    private val authenticationProvider:AuthenticationProvider
) : WebSecurityConfigurerAdapter() {


    override fun configure(http: HttpSecurity) {
        http
            .csrf().disable()
            .httpBasic().disable()
            .formLogin().disable()
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").anonymous()
                .antMatchers("/rest/login/**").permitAll()
                .antMatchers("/vaadinServlet/UIDL/**").permitAll()
                .antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .logout()
                .addLogoutHandler(logoutHandler())
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?goodbye").permitAll()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(LoginUrlAuthenticationEntryPoint("/login"))
    }

    override fun configure(web: WebSecurity) {
        web
            .ignoring().antMatchers(
                "/VAADIN/**"
            )
    }

    override fun configure(auth: AuthenticationManagerBuilder) {
        auth
            .authenticationProvider(authenticationProvider)
    }

    private fun logoutHandler(): LogoutHandler {
        return VaadinSessionClosingLogoutHandler()
    }

    @Bean
    fun myAuthenticationManager(): AuthenticationManager {
        return super.authenticationManagerBean()
    }
}

UPDATE

所以看起来就像是org.springframework.security.web.csrf.CsrfFilter最终抛出一个AccessDeniedException因为 csrf 令牌丢失了...但它不应该这样做,因为我已经禁用了 Spring 的 csrf 保护...


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

REST 请求在“@SpringBootTest”中执行时被阻止,但在我运行应用程序时却未被阻止? 的相关文章

随机推荐