Java MockMVC-如何使用org.hamcrest.Matcher在spring安全集成测试中检查JWT令牌的内容

Java MockMVC-如何使用org.hamcrest.Matcher在spring安全集成测试中检查JWT令牌的内容,java,spring-security,jwt,token,hamcrest,Java,Spring Security,Jwt,Token,Hamcrest,我从MockMvc请求中得到JWT令牌作为响应。我想检查此响应的内容: mockMvc.perform(post("/authorize") .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeEmailAndPassword("test1@app.com", "1111")) .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE) .p

我从MockMvc请求中得到JWT令牌作为响应。我想检查此响应的内容:

mockMvc.perform(post("/authorize")
        .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeEmailAndPassword("test1@app.com", "1111"))
        .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
        .params(params)
        .accept(MediaType.APPLICATION_JSON))
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
    .andDo(print())
    .andExpect(status().isOk())
;
结果将是:

{
    "id_token": "............(long Base64 string)"
}
当我们用JWT.io解码令牌时,我们看到:

{
  "sub": "cc15a160-2d62-4091-b89a-117e77346a58",
  "nbf": 1543846725,
  "auth_level": "trusted",
  "iss": "http://localhost:9090/",
  "exp": 1543847724,
  "iat": 1543846725,
  "nonce": "random_string",
  "jti": "64b8b6e3-5cd0-4242-bcea-2c5d498d64c1"
}
一切都很好,但我想做如下事情:

.andExpect(jsonPath("$.id_token", Matchers.not(null)))
.andExpect(decodeJWT(jsonPath("$.id_token")).getValueOf("nonce"), Matchers.is("random_string"));

我怎样才能做到这一点呢?

我自己找到了答案。。。基本上,使用
org.hamcrest.Matcher
是不可能的,但我们可以将响应分成若干部分,并将它们映射到DTO

首先,我执行一些状态和基本检查,然后将响应返回为
MvcResult

MvcResult result = mockMvc.perform(post("/authorize")
                .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeEmailAndPassword("test1@app.com", "1111"))
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(content)
                .accept(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id_token", Matchers.notNullValue()))
            .andReturn();
然后,我为Jackson反序列化创建了一些DTO:(记住创建类而不是作为内部类,因为Jackson会抱怨“只能使用内部非静态类的无参数构造函数”)

最后,JWT令牌解析比我想象的要简单得多:

String token = mapper.readValue(result.getResponse().getContentAsString(), TokenResponseDTO.class).getIdToken();
JWSObject jwsObject = JWSObject.parse(token);
JWTPayloadDTO payload = mapper.readValue(jwsObject.getPayload().toString(), JWTPayloadDTO.class);

Assert.assertEquals("random_string", payload.getNonce());
... // other checks

非常感谢。你的回答真的帮助了我。
String token = mapper.readValue(result.getResponse().getContentAsString(), TokenResponseDTO.class).getIdToken();
JWSObject jwsObject = JWSObject.parse(token);
JWTPayloadDTO payload = mapper.readValue(jwsObject.getPayload().toString(), JWTPayloadDTO.class);

Assert.assertEquals("random_string", payload.getNonce());
... // other checks