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

Spring Boot-使用自定义预授权表达式和身份验证测试Rest Api

陈季
2023-03-14

我正在寻找如何使用以下设置测试Spring Boot REST API的方法:

@RestController
class SomeRestController {

  @Autowired
  private SomeService someService;

  @GetMapping("/getSome")
  @PreAuthorize("@canGetSome.isValid()")
  public SomeObject getSomeObject() {
    return someService.getSomeObject();
  }
}

_

@Component
public class CanGetSome{

  @Autowired
  private final LoggedUser loggedUser;

  public boolean isValid() {
    return loggedUser.getPermissions().isCanGetSome();
  }
}

_

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
...
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .sessionManagement()
        .sessionFixation().newSession()
        .and()
            .authorizeRequests())
            .anyRequest().authenticated();
  }

//custom LoggedUser object which is initzialized on authentication sucessfull
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public LoggedUser loggedUser() {
  Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  return (LoggedUser) authentication.getPrincipal();
  }
...
}

我的测试用例:

@SpringBootTest(
    classes = SpringBootApplication,
    webEnvironment = RANDOM_PORT)
@ContextConfiguration
class RestSecurityTest extends Specification {

  @Autowired
  private TestRestTemplate testRestTemplate

  @LocalServerPort
  private int port

  @WithCustomMockUser
  def "test testRestTemplare"(){
  expect:
  def respone = testRestTemplate.getForObject('http://localhost:'+ port+'/getSome', String)
  }

_

public class WithCustomMockUserSecurityContextFactory implements WithSecurityContextFactory<WithCustomMockUser> {

  @Override
  public SecurityContext createSecurityContext(WithCustomMockUser annotation) {
    //init securityContext like @WithMockUser but with LoggedUser as principal which return true on loggedUser.getPermissions().isCanGetSome();
  }
}

不幸的是,我在测试中得到以下响应:

{
  "timestamp": 1524759173851,
  "status": 403,
  "error": "Forbidden",
  "message": "Access Denied",
  "path": "/getSome"
}

在请求之后,我还调试了不同的spring过滤器,其中SecurityContext身份验证为null,随后切换为AnonymousAuthenticationToken

我不知道为什么SecurityContext在请求后为null,而不是用@WithCustomMockUser注释初始化的SecurityContext。有没有办法解决这个问题?

共有1个答案

万涵亮
2023-03-14

Spring MVC应该是未来的发展方向。

测试等级:-

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestContext.class, TestWebMvcConfigurerAdapter.class, SecurityConfiguration .class })
@WebAppConfiguration
public class SomeControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

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

    @Test
    public void shouldPreAuthorise() throws Exception {
        this.mockMvc.perform(get("/getSome")
                .with(user("user.name"))
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }

}

测试web配置程序:-

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {
        "your.package.here"
})
public class TestWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {

}

一些模拟对象:-

@Configuration
public class TestContext {

    @Bean
    public SomeService someService() {
        return mock(SomeService.class);
    }

}
 类似资料:
  • 我实现了一个自定义的身份验证过滤器,效果很好。在设置会话并将身份验证对象添加到安全上下文后,我使用外部身份提供程序并重定向到最初请求的URL。 安全配置 过滤逻辑 目前,我的自定义过滤器(身份确认后)只需硬编码一个角色: 然后将该身份验证对象(上面返回)添加到我的SecurityContext,然后再重定向到所需的endpoint: SecurityContextHolder.getContext

  • 在过去的几周里,我一直在努力掌握KeyClope,这样我就可以实现一种使用遗留提供商(基于Oracle,带有会话表和各种奇怪的东西)对用户进行身份验证的方法。我们计划在不久的将来解决这个问题,但目前我们必须解决这个问题,所以我们的想法是在前线使用KeyClope——利用它提供的主要好处,比如SSO——在需要身份验证的应用程序中省略传统的身份验证提供程序。 我读了一些关于构建自定义OIDC身份提供程

  • 踏频/临时是否提供任何类型的身份验证和授权机制来访问节奏服务器/Web-ui以及节奏/时态服务器与工作流/活动工作者之间的通信。我找不到任何关于此的文档。

  • 嗨,伙计们,我正在开发应用程序使用spring boot和spring security在我的应用程序中进行身份验证,我使用自定义令牌,并且我能够成功地对用户进行身份验证。现在我想添加自定义授权到我的应用程序我想通过以下方式进行授权: 我的自定义userDetails服务如下:

  • 我目前正在使用Spring Security开发Spring Boot REST应用程序。我的工作场所使用Auth0(提供用户管理的外部第三方服务)进行身份验证,并已要求我在此应用程序中实现它。身份验证发生在用React编写的前端应用程序中。前端应用程序显示登录表单,并将用户名和密码发送给Auth0,Auth0验证凭据,并在验证用户时返回JWT令牌。 在此之后,前端应用程序将通过头中的JWT令牌从