Micronaut中如何获取x-www-form-urlencoded请求的请求体参数值?
Micronaut 认证层获取表单请求体为空问题解决
问题原因
出现这个问题的核心原因是:Micronaut 基于Netty实现的HTTP请求体是单次消费的流,安全认证过滤器执行优先级高于自定义的AuthenticationProvider逻辑,默认情况下过滤器会读取解析表单参数做基础校验,请求体被消费后没有缓存,后续逻辑再调用httpRequest.getBody()自然返回空。
推荐解决方案:直接通过AuthenticationRequest拿表单参数
不需要额外改配置,也不需要自己读请求体,Micronaut Security 已经自动完成了x-www-form-urlencoded类型请求的表单解析,所有参数都已经封装到方法入参的AuthenticationRequest对象里:
- 表单里的
client_id、client_secret会自动绑定为认证身份和凭证,直接调用authenticationRequest.getIdentity()、authenticationRequest.getSecret()就能拿到 - 其余自定义表单字段(比如你传的
grant_type、scope),把入参强转为FormAuthenticationRequest类型,调用getParameters()就能拿到全量表单键值对
修改后的认证逻辑代码:
@Singleton public class AuthenticationProviderForm implements AuthenticationProvider { @Override public Publisher<AuthenticationResponse> authenticate(@Nullable HttpRequest<?> httpRequest, AuthenticationRequest<?, ?> authenticationRequest) { FormAuthenticationRequest formAuthRequest = (FormAuthenticationRequest) authenticationRequest; // 取全量表单参数 Map<String, String> allFormParams = formAuthRequest.getParameters(); String grantType = allFormParams.get("grant_type"); String scope = allFormParams.get("scope"); String clientId = formAuthRequest.getIdentity().toString(); String clientSecret = formAuthRequest.getSecret().toString(); // 在这里写你的身份认证逻辑即可 return Mono.just(AuthenticationResponse.success(clientId)); } }
备选方案:开启全局请求体缓存
如果你的业务场景必须直接从HttpRequest对象读取原始请求体,可以在配置文件中开启请求体预读缓存,所有请求的请求体会被提前读取缓存,不会出现流被消费完拿不到值的问题。
如果使用application.yml配置,添加如下配置项:
micronaut: server: always-read-request-body: true
注意:这个配置会让所有请求的请求体提前加载到内存,会额外增加服务内存开销,非必要不推荐开启。
补充:Controller层获取表单参数的写法
你当前的Controller方法没有做参数绑定,就算请求体正常也拿不到表单值,需要在方法入参上用@FormData注解绑定对应字段,示例:
@Controller @Secured(SecurityRule.IS_AUTHENTICATED) public class ControllerApi { @Post("/hello") @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public String helloPost(@FormData String grant_type, @FormData String scope){ return "POST hello, grant_type:" + grant_type + ", scope:" + scope; } }
你提供的curl请求可以直接触发上述逻辑,不需要额外调整请求头或者参数格式。
内容的提问来源于stack exchange,提问作者Alan Michel
相关产品推荐
相关产品推荐

