操作 ContainerRequestFilter 的 InputStream
Manipulate InputStream of ContainerRequestFilter
我有一个客户端发送的加密字符串。我正在尝试使用 ContainerRequestFilter 然后 decrypt 拦截字符串并再次设置 InputStream 以便 Jackson 可以使用它 映射到 POJO。
插图:
我的资源
@Path("auth")
public class AuthResource {
@POST
public Response testResource(@Auth AuthUser auth, Person person) {
System.out.println("Recieved Resource:: "+ new Gson().toJson(person));
return null;
}
}
Person.java
public class Person {
private String name;
private int age;
public Person() {};
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
我的过滤器
@Provider
public class MyFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
InputStream inputStream = requestContext.getEntityStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
String theString = writer.toString();
String decryptedMessage = "";
try {
decryptedMessage = JwtToken.decryptPayload(theString);
System.err.println("Decrypted Message: "+decryptedMessage);
} catch (Exception e) {
e.printStackTrace();
}
InputStream stream = new ByteArrayInputStream(decryptedMessage.getBytes(StandardCharsets.UTF_8));
requestContext.setEntityStream(stream);
}
}
我了解到 InputStream 一旦被使用就不能再使用了。但是使用 requestContext.setEntityStream(stream); 我试图再次设置 InputStream 以供 Jackson 使用。
尽管如此,我仍然无法在我的资源中找到这个人object。解密工作正常,因为我已经使用调试器对其进行了测试。
我收到以下错误:415:不支持的媒体类型
编辑 1: 我正在使用高级休息客户端点击 url
Header:
authorization: Basic ZXlKaGRYUm9iM0pwZW1GMGFXOXVJam9pWVcxcGRDSXNJbUZzWnlJNklraFRNalUySW4wLmUzMC5MLUtmOUxQNjFSQ21Bektob2lTR0V4bEJ3RXRUMXhrR3A3bUpIZmFSeV9FOnBhc3M=
原始负载:
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g
负载仅使用 JWT 加密:
Jwts.builder().setPayload(new Gson().toJson(new Person("Amit",22))).signWith(SignatureAlgorithm.HS256, key).compact();
您的请求负载不是 JSON。它是一个 JWT 令牌,其中包含一个编码为 Base64 的 JSON。这是一段文字。因此,请求的 Content-Type
应该是 text/plain
而不是 application/json
:
POST /api/auth HTTP/1.1
Host: example.org
Content-Type: text/plain
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g
您的过滤器修改请求的负载:过滤器从请求负载中获取 JWT 令牌,获取令牌负载,将令牌负载解码为 JSON 字符串并设置 JSON请求负载的字符串。
执行过滤器后,请求将包含一个 JSON 字符串,而不仅仅是一段文本。因此,之后,请求的Content-Type
应该被修改为application/json
。可以通过以下几行来实现:
requestContext.getHeaders().remove(HttpHeaders.CONTENT_TYPE);
requestContext.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
为确保过滤器在资源匹配之前执行,请使用 @PreMatching
.
注释您的过滤器
并且不要忘记使用 @Consumes(MediaType.APPLICATION_JSON)
注释您的资源方法。
我尝试将负载更改为 JSON 文档,如下所示:
"temp":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g"
并在我的过滤器中使用以下代码提取加密的负载:
JsonObject jsonObject = new Gson().fromJson(theString, JsonObject.class);
theString = jsonObject.get("temp").getAsString();
还将资源更改为@Consumes(MediaType.APPLICATION_JSON)
成功了!
我想原因如 pandaadb 所述,Jersey 无法将其识别为 JSON 文档,因此无法将其映射到 Person POJO。
我有一个客户端发送的加密字符串。我正在尝试使用 ContainerRequestFilter 然后 decrypt 拦截字符串并再次设置 InputStream 以便 Jackson 可以使用它 映射到 POJO。
插图:
我的资源
@Path("auth")
public class AuthResource {
@POST
public Response testResource(@Auth AuthUser auth, Person person) {
System.out.println("Recieved Resource:: "+ new Gson().toJson(person));
return null;
}
}
Person.java
public class Person {
private String name;
private int age;
public Person() {};
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
我的过滤器
@Provider
public class MyFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
InputStream inputStream = requestContext.getEntityStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
String theString = writer.toString();
String decryptedMessage = "";
try {
decryptedMessage = JwtToken.decryptPayload(theString);
System.err.println("Decrypted Message: "+decryptedMessage);
} catch (Exception e) {
e.printStackTrace();
}
InputStream stream = new ByteArrayInputStream(decryptedMessage.getBytes(StandardCharsets.UTF_8));
requestContext.setEntityStream(stream);
}
}
我了解到 InputStream 一旦被使用就不能再使用了。但是使用 requestContext.setEntityStream(stream); 我试图再次设置 InputStream 以供 Jackson 使用。
尽管如此,我仍然无法在我的资源中找到这个人object。解密工作正常,因为我已经使用调试器对其进行了测试。
我收到以下错误:415:不支持的媒体类型
编辑 1: 我正在使用高级休息客户端点击 url
Header:
authorization: Basic ZXlKaGRYUm9iM0pwZW1GMGFXOXVJam9pWVcxcGRDSXNJbUZzWnlJNklraFRNalUySW4wLmUzMC5MLUtmOUxQNjFSQ21Bektob2lTR0V4bEJ3RXRUMXhrR3A3bUpIZmFSeV9FOnBhc3M=
原始负载:
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g
负载仅使用 JWT 加密:
Jwts.builder().setPayload(new Gson().toJson(new Person("Amit",22))).signWith(SignatureAlgorithm.HS256, key).compact();
您的请求负载不是 JSON。它是一个 JWT 令牌,其中包含一个编码为 Base64 的 JSON。这是一段文字。因此,请求的 Content-Type
应该是 text/plain
而不是 application/json
:
POST /api/auth HTTP/1.1
Host: example.org
Content-Type: text/plain
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g
您的过滤器修改请求的负载:过滤器从请求负载中获取 JWT 令牌,获取令牌负载,将令牌负载解码为 JSON 字符串并设置 JSON请求负载的字符串。
执行过滤器后,请求将包含一个 JSON 字符串,而不仅仅是一段文本。因此,之后,请求的Content-Type
应该被修改为application/json
。可以通过以下几行来实现:
requestContext.getHeaders().remove(HttpHeaders.CONTENT_TYPE);
requestContext.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
为确保过滤器在资源匹配之前执行,请使用 @PreMatching
.
并且不要忘记使用 @Consumes(MediaType.APPLICATION_JSON)
注释您的资源方法。
我尝试将负载更改为 JSON 文档,如下所示:
"temp":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQW1pdCIsImFnZSI6MjJ9.-rO6yhYJ--3ZzVCaHFw1hF-s533foYY6vVAuyRh3Q9g"
并在我的过滤器中使用以下代码提取加密的负载:
JsonObject jsonObject = new Gson().fromJson(theString, JsonObject.class);
theString = jsonObject.get("temp").getAsString();
还将资源更改为@Consumes(MediaType.APPLICATION_JSON)
成功了!
我想原因如 pandaadb 所述,Jersey 无法将其识别为 JSON 文档,因此无法将其映射到 Person POJO。