Spring 安全 OAuth2 接受 JSON
Spring security OAuth2 accept JSON
我从 Spring OAuth2 开始。我想以 application/json 格式将用户名和密码发送到 POST 正文中的 /oauth/token 端点。
curl -X POST -H "Authorization: Basic YWNtZTphY21lc2VjcmV0" -H "Content-Type: application/json" -d '{
"username": "user",
"password": "password",
"grant_type": "password"
}' "http://localhost:9999/api/oauth/token"
这可能吗?
你能给我一个建议吗?
The client makes a request to the token endpoint by sending the
following parameters using the "application/x-www-form-urlencoded"
访问令牌请求应使用application/x-www-form-urlencoded
。
在 Spring 安全性中,资源所有者密码凭证授予流程由 ResourceOwnerPasswordTokenGranter#getOAuth2Authentication
在 Spring 安全性中处理:
protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) {
Map parameters = clientToken.getAuthorizationParameters();
String username = (String)parameters.get("username");
String password = (String)parameters.get("password");
UsernamePasswordAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(username, password);
您可以发送username
和password
来请求参数。
如果你真的需要使用JSON,有一个解决方法。如您所见,username
和 password
是从请求参数中检索的。因此,如果您将它们从 JSON 主体传递到请求参数中,它将起作用。
思路如下:
- 创建自定义 spring 安全过滤器。
- 在您的自定义过滤器中,创建一个 class 到 subclass
HttpRequestWrapper
。 class 允许您包装原始请求并从 JSON. 获取参数
- 在
HttpRequestWrapper
的子 class 中,解析请求正文中的 JSON 以获得 username
、password
和 grant_type
,并将它们与原始请求参数一起放入新的 HashMap
中。然后,将 getParameterValues
、getParameter
、getParameterNames
和 getParameterMap
的方法重写为新 HashMap
中的 return 值
- 将您包装的请求传递到过滤器链中。
- 在 Spring 安全配置中配置您的自定义过滤器。
希望对您有所帮助
解决方案(不确定是否正确,但它确实有效):
资源服务器配置:
@Configuration
public class ServerEndpointsConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(jsonFilter, ChannelProcessingFilter.class)
.csrf().and().httpBasic().disable()
.authorizeRequests()
.antMatchers("/test").permitAll()
.antMatchers("/secured").authenticated();
}
}
过滤器:
@Component
@Order(value = Integer.MIN_VALUE)
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
if (Objects.equals(request.getContentType(), "application/json") && Objects.equals(((RequestFacade) request).getServletPath(), "/oauth/token")) {
InputStream is = request.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] json = buffer.toByteArray();
HashMap<String, String> result = new ObjectMapper().readValue(json, HashMap.class);
HashMap<String, String[]> r = new HashMap<>();
for (String key : result.keySet()) {
String[] val = new String[1];
val[0] = result.get(key);
r.put(key, val);
}
String[] val = new String[1];
val[0] = ((RequestFacade) request).getMethod();
r.put("_method", val);
HttpServletRequest s = new MyServletRequestWrapper(((HttpServletRequest) request), r);
chain.doFilter(s, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}
请求包装器:
public class MyServletRequestWrapper extends HttpServletRequestWrapper {
private final HashMap<String, String[]> params;
public MyServletRequestWrapper(HttpServletRequest request, HashMap<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
授权服务器配置(为 /oauth/token 端点禁用基本身份验证:
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients(); // Disable /oauth/token Http Basic Auth
}
...
}
您也可以修改@jakub-kopřiva解决方案以支持oauth的http basic auth。
资源服务器配置:
@Configuration
public class ServerEndpointsConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(jsonFilter, BasicAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests()
.antMatchers("/test").permitAll()
.antMatchers("/secured").authenticated();
}
}
使用内部 RequestWrapper 过滤
@Component
public class JsonToUrlEncodedAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (Objects.equals(request.getServletPath(), "/oauth/token") && Objects.equals(request.getContentType(), "application/json")) {
byte[] json = ByteStreams.toByteArray(request.getInputStream());
Map<String, String> jsonMap = new ObjectMapper().readValue(json, Map.class);;
Map<String, String[]> parameters =
jsonMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> new String[]{e.getValue()})
);
HttpServletRequest requestWrapper = new RequestWrapper(request, parameters);
filterChain.doFilter(requestWrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
private class RequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> params;
RequestWrapper(HttpServletRequest request, Map<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
}
并且您还需要允许 x-www-form-urlencoded 身份验证
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
...
}
通过这种方法,您仍然可以对 oauth 令牌使用基本身份验证,并使用 json 请求令牌,如下所示:
Header:
Authorization: Basic bG9yaXpvbfgzaWNwYQ==
Body:
{
"grant_type": "password",
"username": "admin",
"password": "1234"
}
使用 Spring Security 5 我只需要添加 .allowFormAuthenticationForClients() + 另一个答案中提到的 JsontoUrlEncodedAuthenticationFilter 来让它接受 json 除了 x-form post 数据。不需要注册资源服务器什么的。
您可以修改@jakub-kopřiva 解决方案以仅使用以下代码实现授权服务器。
@Configuration
@Order(Integer.MIN_VALUE)
public class AuthorizationServerSecurityConfiguration
extends org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerSecurityConfiguration {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.addFilterBefore(jsonFilter, ChannelProcessingFilter.class);
super.configure(httpSecurity);
}
}
你好,基于@Jakub Kopřiva 的回答,我已经进行了改进以创建有效的集成测试。
如您所知,Catalina RequestFacade 在 Junit 中抛出错误,mockmvc 使用的 MockHttpServletRequest 不包含我在过滤器中预期的字段 "request"(因此在使用 getDeclaredField() 时抛出 NoSuchFieldException):
Field f = request.getClass().getDeclaredField("request");
这就是我使用 "Rest Assured" 的原因。然而,此时我 运行 陷入另一个问题,即无论出于何种原因,来自 'application/json' 的内容类型被覆盖为 'application/json; charset=utf8',即使我使用 MediaType.APPLICATION_JSON_VALUE
。但是,该条件会查找位于 MediaType.APPLICATION_JSON_UTF8_VALUE
之后的类似 'application/json;charset=UTF-8' 的内容,总而言之,这将始终为假。
因此,当我在 PHP 中编码时,我的行为就像以前一样,并且我已经规范化了字符串(所有字符都是小写的,没有空格)。
在此之后集成测试终于通过了。
----JsonToUrlEncodedAuthenticationFilter.java
package com.example.springdemo.configs;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.apache.catalina.connector.Request;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.security.web.savedrequest.Enumerator;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Order(value = Integer.MIN_VALUE)
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
private final ObjectMapper mapper;
public JsonToUrlEncodedAuthenticationFilter(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
@SneakyThrows
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Field f = request.getClass().getDeclaredField("request");
f.setAccessible(true);
Request realRequest = (Request) f.get(request);
//Request content type without spaces (inner spaces matter)
//trim deletes spaces only at the beginning and at the end of the string
String contentType = realRequest.getContentType().toLowerCase().chars()
.mapToObj(c -> String.valueOf((char) c))
.filter(x->!x.equals(" "))
.collect(Collectors.joining());
if ((contentType.equals(MediaType.APPLICATION_JSON_UTF8_VALUE.toLowerCase())||
contentType.equals(MediaType.APPLICATION_JSON_VALUE.toLowerCase()))
&& Objects.equals((realRequest).getServletPath(), "/oauth/token")) {
InputStream is = realRequest.getInputStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is), 16384)) {
String json = br.lines()
.collect(Collectors.joining(System.lineSeparator()));
HashMap<String, String> result = mapper.readValue(json, HashMap.class);
HashMap<String, String[]> r = new HashMap<>();
for (String key : result.keySet()) {
String[] val = new String[1];
val[0] = result.get(key);
r.put(key, val);
}
String[] val = new String[1];
val[0] = (realRequest).getMethod();
r.put("_method", val);
HttpServletRequest s = new MyServletRequestWrapper(((HttpServletRequest) request), r);
chain.doFilter(s, response);
}
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
class MyServletRequestWrapper extends HttpServletRequestWrapper {
private final HashMap<String, String[]> params;
MyServletRequestWrapper(HttpServletRequest request, HashMap<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
我从 Spring OAuth2 开始。我想以 application/json 格式将用户名和密码发送到 POST 正文中的 /oauth/token 端点。
curl -X POST -H "Authorization: Basic YWNtZTphY21lc2VjcmV0" -H "Content-Type: application/json" -d '{
"username": "user",
"password": "password",
"grant_type": "password"
}' "http://localhost:9999/api/oauth/token"
这可能吗?
你能给我一个建议吗?
The client makes a request to the token endpoint by sending the
following parameters using the "application/x-www-form-urlencoded"
访问令牌请求应使用application/x-www-form-urlencoded
。
在 Spring 安全性中,资源所有者密码凭证授予流程由 ResourceOwnerPasswordTokenGranter#getOAuth2Authentication
在 Spring 安全性中处理:
protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) {
Map parameters = clientToken.getAuthorizationParameters();
String username = (String)parameters.get("username");
String password = (String)parameters.get("password");
UsernamePasswordAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(username, password);
您可以发送username
和password
来请求参数。
如果你真的需要使用JSON,有一个解决方法。如您所见,username
和 password
是从请求参数中检索的。因此,如果您将它们从 JSON 主体传递到请求参数中,它将起作用。
思路如下:
- 创建自定义 spring 安全过滤器。
- 在您的自定义过滤器中,创建一个 class 到 subclass
HttpRequestWrapper
。 class 允许您包装原始请求并从 JSON. 获取参数
- 在
HttpRequestWrapper
的子 class 中,解析请求正文中的 JSON 以获得username
、password
和grant_type
,并将它们与原始请求参数一起放入新的HashMap
中。然后,将getParameterValues
、getParameter
、getParameterNames
和getParameterMap
的方法重写为新HashMap
中的 return 值
- 将您包装的请求传递到过滤器链中。
- 在 Spring 安全配置中配置您的自定义过滤器。
希望对您有所帮助
解决方案(不确定是否正确,但它确实有效):
资源服务器配置:
@Configuration
public class ServerEndpointsConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(jsonFilter, ChannelProcessingFilter.class)
.csrf().and().httpBasic().disable()
.authorizeRequests()
.antMatchers("/test").permitAll()
.antMatchers("/secured").authenticated();
}
}
过滤器:
@Component
@Order(value = Integer.MIN_VALUE)
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
if (Objects.equals(request.getContentType(), "application/json") && Objects.equals(((RequestFacade) request).getServletPath(), "/oauth/token")) {
InputStream is = request.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] json = buffer.toByteArray();
HashMap<String, String> result = new ObjectMapper().readValue(json, HashMap.class);
HashMap<String, String[]> r = new HashMap<>();
for (String key : result.keySet()) {
String[] val = new String[1];
val[0] = result.get(key);
r.put(key, val);
}
String[] val = new String[1];
val[0] = ((RequestFacade) request).getMethod();
r.put("_method", val);
HttpServletRequest s = new MyServletRequestWrapper(((HttpServletRequest) request), r);
chain.doFilter(s, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}
请求包装器:
public class MyServletRequestWrapper extends HttpServletRequestWrapper {
private final HashMap<String, String[]> params;
public MyServletRequestWrapper(HttpServletRequest request, HashMap<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
授权服务器配置(为 /oauth/token 端点禁用基本身份验证:
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients(); // Disable /oauth/token Http Basic Auth
}
...
}
您也可以修改@jakub-kopřiva解决方案以支持oauth的http basic auth。
资源服务器配置:
@Configuration
public class ServerEndpointsConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(jsonFilter, BasicAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests()
.antMatchers("/test").permitAll()
.antMatchers("/secured").authenticated();
}
}
使用内部 RequestWrapper 过滤
@Component
public class JsonToUrlEncodedAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (Objects.equals(request.getServletPath(), "/oauth/token") && Objects.equals(request.getContentType(), "application/json")) {
byte[] json = ByteStreams.toByteArray(request.getInputStream());
Map<String, String> jsonMap = new ObjectMapper().readValue(json, Map.class);;
Map<String, String[]> parameters =
jsonMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> new String[]{e.getValue()})
);
HttpServletRequest requestWrapper = new RequestWrapper(request, parameters);
filterChain.doFilter(requestWrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
private class RequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> params;
RequestWrapper(HttpServletRequest request, Map<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
}
并且您还需要允许 x-www-form-urlencoded 身份验证
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
...
}
通过这种方法,您仍然可以对 oauth 令牌使用基本身份验证,并使用 json 请求令牌,如下所示:
Header:
Authorization: Basic bG9yaXpvbfgzaWNwYQ==
Body:
{
"grant_type": "password",
"username": "admin",
"password": "1234"
}
使用 Spring Security 5 我只需要添加 .allowFormAuthenticationForClients() + 另一个答案中提到的 JsontoUrlEncodedAuthenticationFilter 来让它接受 json 除了 x-form post 数据。不需要注册资源服务器什么的。
您可以修改@jakub-kopřiva 解决方案以仅使用以下代码实现授权服务器。
@Configuration
@Order(Integer.MIN_VALUE)
public class AuthorizationServerSecurityConfiguration
extends org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerSecurityConfiguration {
@Autowired
JsonToUrlEncodedAuthenticationFilter jsonFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.addFilterBefore(jsonFilter, ChannelProcessingFilter.class);
super.configure(httpSecurity);
}
}
你好,基于@Jakub Kopřiva 的回答,我已经进行了改进以创建有效的集成测试。
如您所知,Catalina RequestFacade 在 Junit 中抛出错误,mockmvc 使用的 MockHttpServletRequest 不包含我在过滤器中预期的字段 "request"(因此在使用 getDeclaredField() 时抛出 NoSuchFieldException):
Field f = request.getClass().getDeclaredField("request");
这就是我使用 "Rest Assured" 的原因。然而,此时我 运行 陷入另一个问题,即无论出于何种原因,来自 'application/json' 的内容类型被覆盖为 'application/json; charset=utf8',即使我使用 MediaType.APPLICATION_JSON_VALUE
。但是,该条件会查找位于 MediaType.APPLICATION_JSON_UTF8_VALUE
之后的类似 'application/json;charset=UTF-8' 的内容,总而言之,这将始终为假。
因此,当我在 PHP 中编码时,我的行为就像以前一样,并且我已经规范化了字符串(所有字符都是小写的,没有空格)。
在此之后集成测试终于通过了。
----JsonToUrlEncodedAuthenticationFilter.java
package com.example.springdemo.configs;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.apache.catalina.connector.Request;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.security.web.savedrequest.Enumerator;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Order(value = Integer.MIN_VALUE)
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
private final ObjectMapper mapper;
public JsonToUrlEncodedAuthenticationFilter(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
@SneakyThrows
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Field f = request.getClass().getDeclaredField("request");
f.setAccessible(true);
Request realRequest = (Request) f.get(request);
//Request content type without spaces (inner spaces matter)
//trim deletes spaces only at the beginning and at the end of the string
String contentType = realRequest.getContentType().toLowerCase().chars()
.mapToObj(c -> String.valueOf((char) c))
.filter(x->!x.equals(" "))
.collect(Collectors.joining());
if ((contentType.equals(MediaType.APPLICATION_JSON_UTF8_VALUE.toLowerCase())||
contentType.equals(MediaType.APPLICATION_JSON_VALUE.toLowerCase()))
&& Objects.equals((realRequest).getServletPath(), "/oauth/token")) {
InputStream is = realRequest.getInputStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is), 16384)) {
String json = br.lines()
.collect(Collectors.joining(System.lineSeparator()));
HashMap<String, String> result = mapper.readValue(json, HashMap.class);
HashMap<String, String[]> r = new HashMap<>();
for (String key : result.keySet()) {
String[] val = new String[1];
val[0] = result.get(key);
r.put(key, val);
}
String[] val = new String[1];
val[0] = (realRequest).getMethod();
r.put("_method", val);
HttpServletRequest s = new MyServletRequestWrapper(((HttpServletRequest) request), r);
chain.doFilter(s, response);
}
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
class MyServletRequestWrapper extends HttpServletRequestWrapper {
private final HashMap<String, String[]> params;
MyServletRequestWrapper(HttpServletRequest request, HashMap<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public String getParameter(String name) {
if (this.params.containsKey(name)) {
return this.params.get(name)[0];
}
return "";
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Enumerator<>(params.keySet());
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}