Java REST请求在`@SpringBootTest`中执行时被阻止,但在我运行应用程序时未被阻止?
我在Java REST请求在`@SpringBootTest`中执行时被阻止,但在我运行应用程序时未被阻止?,java,rest,spring-security,jax-rs,vaadin,Java,Rest,Spring Security,Jax Rs,Vaadin,我在/REST有一个带有Jersey REST api的Spring Boot应用程序: @组件 @应用程序路径(“/rest”) 公共类重新启动应用程序扩展了ResourceConfig{ 公共重新应用程序(){ 软件包(“ch.cypherk.myapp.service.rest”); } } 这是允许用户登录的控制器: @Service @Path("/login") class LoginRestController @Inject constructor( private v
/REST
有一个带有Jersey REST api的Spring Boot应用程序:
@组件
@应用程序路径(“/rest”)
公共类重新启动应用程序扩展了ResourceConfig{
公共重新应用程序(){
软件包(“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)
}
}
在哪里
@Service
class MyAuthenticationProvider (
...
): AbstractUserDetailsAuthenticationProvider() {
@Transactional
override fun authenticate(authentication: Authentication?): Authentication {
return super.authenticate(authentication)
}
...
}
只是一个添加了一系列额外检查的自定义实现
如果我启动Spring Boot应用程序并使用postman向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
(禁止)
为什么?
上面的代码正在使用,但问题不在于框架,因为我尝试用
得到了同样的错误
我在我的LoginRestController
的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()
}
}
更新
所以看起来是
org.springframework.security.web.csrf.CsrfFilter
抛出了一个AccessDeniedException
,因为csrf令牌丢失了。。。但它不应该这样做,因为我已经禁用了Spring的csrf保护…为什么要在Spring Boot中使用JAX-RS?@SimonMartinelli,因为我们正在将thorntail应用程序迁移到Spring Boot,不想一下子改变太多。稍后我们可能会切换到SpringMVC,但现在,首要任务是让JAX-RS正常工作。您如何登录到您的应用程序?
@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()
}
}