【问题标题】:MockMvc using a mock session to bypass securityMockMvc 使用模拟会话绕过安全性
【发布时间】:2016-09-05 23:17:18
【问题描述】:

我正在开发一套微服务中的 spring-boot 微服务。服务端点都使用两个功能进行保护:@PreAuthorize 注释和提供额外无状态身份验证的自定义 GenericFilterBean。

有些人使用 MockMvc 首先发布到登录 url,然后从指定的端点获取。这对我来说是个问题,因为登录是由不同的微服务执行的。

我在没有完全理解的情况下做了不同的尝试,可以总结为:

  1. 通过其他微服务登录以获取设置了 cookie 的会话
  2. 模拟会话以使用虚假 cookie
  3. 禁用安全和自定义过滤器

MockMvc 不允许调用外部 url 来执行登录,所以第一个被排除在外。模拟会话似乎没有给我一种设置 cookie 的方法——我只在响应对象上看到 addCookie。禁用自定义过滤器没有导致任何事情发生(也许我做错了)。

在我看来,正确的测试方法是进行有效的模拟会话并保持安全性。我不知道如何继续。

spring-boot 父 pom 是:spring-cloud-starter-parent - Brixton.M4

如何测试单个微服务并绕过安全性?

【问题讨论】:

    标签: java spring junit spring-security spring-boot


    【解决方案1】:

    不久前我遇到过类似的问题,我花了一些时间才找到答案,不确定这是否能解决您的问题,但我可以使用以下方法使用 mockMvc 进行身份验证

    创建一个负责身份验证的类。可能是这样的

    public class Auth {  
    
        @Autowired
        private WebApplicationContext wac;
    
        @Autowired
        private FilterChainProxy springSecurityFilter;
    
        protected MockMvc mockMvc;
        protected MockHttpSession session;
    
        public void setup() throws Exception{
            this.session = new MockHttpSession();
            this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
                    .addFilters(springSecurityFilter)
                    .build();
        }
    
        protected void setAuthentication(String user, String password, MockHttpSession session){
            Authentication authentication = new UsernamePasswordAuthenticationToken(user, password);
            SecurityContext securityContext = SecurityContextHolder.getContext();
            securityContext.setAuthentication(authentication);
    
            session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,securityContext);
        }
    }
    

    现在您可以简单地扩展该类并使用方法 setAuthenticatio 登录并执行测试。比如

    public class myTest extends Auth {
         @Test
         public void test{ 
             setAuthentication('user', 'password', session);
             // perform you tests using mockmvc
             // mockMvc.perform(post('url')...
    
         }
    
    }
    

    【讨论】:

    • 是的 - 这确实让我解决了我的问题!我可以调试过滤器,然后看到它需要一个带有一系列签名值的标头,我可以使用代理从常规调用中刮取这些值。 mockMvc.perform(get("/").header("myheader","token"));谢谢!
    • 得到No qualifying bean of type 'org.springframework.security.web.FilterChainProxy' :-(
    • 在基类中用@Before注释setup方法不是更好吗?对我来说,需要自动调用 setup 方法。
    猜你喜欢
    • 2021-10-15
    • 2018-01-03
    • 2012-10-07
    • 2022-09-28
    • 2016-02-05
    • 2019-05-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    相关资源
    最近更新 更多