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

     2023-02-27     217

关键词:

【中文标题】Spring Boot - 使用自定义 PreAuthorize 表达式和身份验证测试 Rest Api【英文标题】:Spring Boot - Test Rest Api With Custom PreAuthorize Expression and Authentication 【发布时间】:2018-10-07 10:53:00 【问题描述】:

我正在寻找一种如何使用以下设置测试 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 在请求后为空,而不是使用 @WithCustomMockUser 注释初始化的 SecurityContext。任何想法如何解决它?

【问题讨论】:

它在您的测试之外工作吗? 你试过this吗?我通过了一个类似的问题,这个解决方案(有一些变化)对我有用。试试看,在这里告诉我们结果。 PS.:尝试使用 MockMvc,我无法使用 TestRestTemplate。 【参考方案1】:

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());
    


测试网页配置器:-

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);
    


【讨论】:

是否可以使用 spock 进行此设置?

Spring Boot 在自定义类中使用组件? [关闭]

】SpringBoot在自定义类中使用组件?[关闭]【英文标题】:SpringBootusecomponentinacustomclass?[closed]【发布时间】:2021-10-0319:02:12【问题描述】:我有一个redis工具:@ComponentpublicclassRedisUtil@AutowiredprivateStringRedisTemplatestringRedisTemplate;publicSt... 查看详情

如何为 Spring Boot Rest 使用自定义异常?

】如何为SpringBootRest使用自定义异常?【英文标题】:HowtouseCustomExceptionforSpringBootRest?【发布时间】:2016-10-3110:54:30【问题描述】:我正在使用SpringBoot连接到MySQL5数据库(通过JPA)以及用于服务器端的SpringRest。我的POJO:@Entitypubl... 查看详情

Spring Boot - 使用 RestControllerAdvice 的全局自定义异常处理机制

】SpringBoot-使用RestControllerAdvice的全局自定义异常处理机制【英文标题】:SpringBoot-GlobalCustomExceptionHandlingMechanismusingRestControllerAdvice【发布时间】:2018-01-0409:38:16【问题描述】:我正在为RestfulWeb服务使用SpringBoot。尝试设置一个全... 查看详情

Spring Boot FreeMarker:如何动态使用自定义模板?

】SpringBootFreeMarker:如何动态使用自定义模板?【英文标题】:SpringBootFreeMarker:Howtousecustomtemplateonthefly?【发布时间】:2021-11-2705:05:55【问题描述】:我想在我的SpringBoot应用中使用freemarker。模板将从数据库或文件中加载,但我如... 查看详情

在 Spring Boot 中使用自定义错误 html 文件

】在SpringBoot中使用自定义错误html文件【英文标题】:Usingacustomerrorhtmlfileinspringboot【发布时间】:2019-05-0818:00:45【问题描述】:我有一个/error的url映射到我的errorPage.html,但它没有重定向到这个,我得到了正常的默认springboot错误... 查看详情

使用 Okta Spring Boot Starter 的自定义权限

】使用OktaSpringBootStarter的自定义权限【英文标题】:UsecustomauthoritieswithOktaSpringBootStarter【发布时间】:2020-10-1911:25:12【问题描述】:我正在使用OktaSpringBootStarter的版本1.4.0来验证传入的JWT令牌。通过使用Starter,身份验证和授权都... 查看详情

Spring Boot 不为 ZonedDateTime 使用自定义反序列化器

】SpringBoot不为ZonedDateTime使用自定义反序列化器【英文标题】:SpringBootdoesn\'tusecustomdeserializerforZonedDateTime【发布时间】:2019-01-0100:04:47【问题描述】:我正在尝试设置我的SpringBoot配置以使用我的自定义serializer和deserializer。反序... 查看详情

spring boot spring security 基于自定义令牌的身份验证和自定义授权

】springbootspringsecurity基于自定义令牌的身份验证和自定义授权【英文标题】:springbootspringsecuritycustomtokenbasedauthenticationandcustomauthorization【发布时间】:2016-06-0915:38:11【问题描述】:大家好,我正在开发应用程序,在我的应用程... 查看详情

自定义json(使用spring boot反序列化

】自定义json(使用springboot反序列化【英文标题】:Customjson(de)serializewithspringboot【发布时间】:2016-12-3121:32:01【问题描述】:可以用springboot创建一个JsonSerialize和Deserialize吗?我把我的appliation.properties这一行放在了spring.jackson.date-... 查看详情

在 Spring Boot 端点上使用自定义杰克逊映射器

】在SpringBoot端点上使用自定义杰克逊映射器【英文标题】:Usecustomjacksonmapperonspringbootendpoints【发布时间】:2017-06-2820:52:21【问题描述】:我想在从AbstractEndpoints派生的端点上使用不同的jacksonObjectMapper实例(而不是在其他映射的u... 查看详情

如何使用 Spring Boot 2 为 Grafana 创建自定义指标端点?

】如何使用SpringBoot2为Grafana创建自定义指标端点?【英文标题】:HowtocreateacustommetricsendpointforGrafanausingSpringBoot2?【发布时间】:2020-10-0203:40:56【问题描述】:我正在尝试学习Grafana并使用SpringBoot2、Prometheus和Grafana来创建应用程序... 查看详情

springboot怎么自定义一个starter

SpringBoot怎么自定义一个Starterstarter是什么spring-boot-starter是spring-boot的一个非常重要组成部分。spring-boot-starter可以理解为一个可拔插式的组件。它可以让模块开发独立化,相互间依赖更加松散,也可以更加方便地集成。  &n... 查看详情

自定义 Spring Boot 启动脚本

】自定义SpringBoot启动脚本【英文标题】:CustomizeSpringBootlaunchscript【发布时间】:2022-01-2401:02:32【问题描述】:我有一个典型的SpringBoot2.x应用程序。我目前正在使用Docker部署应用程序。我还在使用“分发”提供的内置shell脚本—... 查看详情

有啥比在 Java Spring Boot 中使用自定义查询更好的方法?

】有啥比在JavaSpringBoot中使用自定义查询更好的方法?【英文标题】:WhatisthebetterwaythanusingcustomizedqueryinJavaSpringBoot?有什么比在JavaSpringBoot中使用自定义查询更好的方法?【发布时间】:2018-11-0620:18:54【问题描述】:这是在我的Ser... 查看详情

使用自定义分隔符通过 Spring Boot 生成 DDL

】使用自定义分隔符通过SpringBoot生成DDL【英文标题】:GenerateDDLwithspringbootusingacustomdelimiter【发布时间】:2017-06-0911:42:21【问题描述】:我想使用SpringBootv1.4.3和JPA-Hibernate5.0.11生成创建和删除ddl脚本。我发现的大多数答案都使用ja... 查看详情

在 Spring Boot 中使用 prometheus 自定义指标

】在SpringBoot中使用prometheus自定义指标【英文标题】:UsingprometheuscustommetricswithSpringBoot【发布时间】:2020-08-2222:11:49【问题描述】:我不确定这是一个错误,但我在过去一天尝试实现这个库,但没有任何结果。我认为这可能与依... 查看详情

为啥使用 webflux 进行 spring boot 测试会忽略自定义 jackson 模块

】为啥使用webflux进行springboot测试会忽略自定义jackson模块【英文标题】:Whydoesspringboottestwithwebfluxignorecustomjacksonmodule为什么使用webflux进行springboot测试会忽略自定义jackson模块【发布时间】:2018-10-2001:54:40【问题描述】:我正在使... 查看详情

在 Spring Boot 中使用自定义代码进行响应 [重复]

】在SpringBoot中使用自定义代码进行响应[重复]【英文标题】:RespondingWithcustomcodeinspringboot[duplicate]【发布时间】:2020-01-0605:54:47【问题描述】:我正在使用SpringBoot创建一个Web服务器。现在作为响应,我想在某些api访问服务器时发... 查看详情