错误信息:org.springframework.web.util.NestedServletException: Request processing failed; nested exception is error="invalid_request", error_description="Missing grant type"
错误代码配置:
@Autowired
protected WebApplicationContext wac;
@Autowired
protected FilterChainProxy springSecurityFilterChain;
protected MockMvc mockMvc;
@Before
public void prepare1() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.addFilter(springSecurityFilterChain).build();
}
protected void auth(OAuth2Form oAuth2Form) throws Exception {
OAuth2Token authToken = JsonUtil.readValue(mockMvc.perform(post(SecurityConstants.DEFAULT_OAUTH_TOKEN_URL)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", AUTHORIZATION)
.content(oAuth2Form.toString()))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(), new TypeReference<OAuth2Token>() {
});
assertNotNull(authToken);
RegistrationMockJunit.authToken = authToken;
}
错误原因:该代码使用post并且使用json的格式来认证用户,我的应用代码中有一个过滤器。它的作用是读取post的APPLICATION_JSON_UTF8数据转成APPLICATION_FORM_URLENCODED(oauth2不支持APPLICATION_JSON_UTF8)。当使用junit的时候没有进入那个过滤器,因为过滤器是保存在ApplicationFilterChain中的,不是保存在FilterChainProxy,使用junit的时候ApplicationFilterChain将替换成MockFilterChain,所以有以上的错误。
解决办法将代码采用APPLICATION_FORM_URLENCODED格式提交
protected void auth(OAuth2Form oAuth2Form) throws Exception {
OAuth2Token authToken = JsonUtil.readValue(mockMvc.perform(post(SecurityConstants.DEFAULT_OAUTH_TOKEN_URL)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", AUTHORIZATION)
.params(oAuth2Form.convert()))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString(), new TypeReference<OAuth2Token>() {
});
assertNotNull(authToken);
RegistrationMockJunit.authToken = authToken;
}
@Getter
public static class OAuth2Form implements Serializable {
@JsonProperty("grant_type")
private String grantType;
private String username;
private String password;
private String scope;
public OAuth2Form(String grantType, String username, String password, String scope) {
this.grantType = grantType;
this.username = username;
this.password = password;
this.scope = scope;
}
public OAuth2Form(String username, String password) {
this.grantType = "password";
this.username = username;
this.password = password;
this.scope = "all";
}
public String toString() {
try {
return JsonUtil.serialize(this);
} catch (IOException e) {
return "";
}
}
public MultiValueMap<String, String> convert(){
MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
result.add("grant_type", this.grantType);
result.add("username", this.username);
result.add("password", this.password);
result.add("scope", this.scope);
return result;
}
}