在 OkHttp 库中使用拦截器
Working with Interceptors in OkHttp library
我需要生成带有所有请求参数的签名认证:
- 查询
- 方法
- Body
- 安全令牌
所以,我写了一个小的 SignatureInterceptor class:
public class SignatureInterceptor implements Interceptor {
private String token;
private String signature = "";
private String method;
private String query;
public SignatureInterceptor() {
this.token = "456456456456";
}
@Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
method = originalRequest.method();
query = originalRequest.urlString();
Request authenticatedRequest = originalRequest.newBuilder()
.method(originalRequest.method(), authenticate(originalRequest.body()))
.addHeader("signature", signature)
.build();
return chain.proceed(authenticatedRequest);
}
private RequestBody authenticate(final RequestBody body) {
return new RequestBody() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override
public long contentLength() throws IOException {
return -1;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink authSink = Okio.buffer(sink);
body.writeTo(sink);
String data = authSink.buffer().readUtf8();
signature = generateSignature(method, query, data, token);
authSink.close();
}
};
}
}
问题是,对于拦截器,结果在执行期间流式传输,所以我无法在处理之前获取签名值。
那么,is-there 一种在 header 中插入在 writeTo() 流方法中生成的签名值的聪明方法?
已更新 根据@Jesse 回答的代码。
private class SignatureInterceptor implements Interceptor {
@Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
String data = "";
if (originalRequest.body() != null) {
BufferedSink authSink = new Buffer();
originalRequest.body().writeTo(authSink);
data = authSink.buffer().readUtf8();
authSink.close();
}
Request authenticatedRequest = originalRequest.newBuilder()
.addHeader(HEADER_SIGNATURE, buildSignature(data))
.build();
return chain.proceed(authenticatedRequest);
}
}
您不需要创建自己的 RequestBody class;仅当您转换 body.
时才有必要
将 writeTo
方法的内容移动到 intercept
中,这样您就可以在调用 proceed
之前计算签名。使用该签名添加 header.
我需要生成带有所有请求参数的签名认证:
- 查询
- 方法
- Body
- 安全令牌
所以,我写了一个小的 SignatureInterceptor class:
public class SignatureInterceptor implements Interceptor {
private String token;
private String signature = "";
private String method;
private String query;
public SignatureInterceptor() {
this.token = "456456456456";
}
@Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
method = originalRequest.method();
query = originalRequest.urlString();
Request authenticatedRequest = originalRequest.newBuilder()
.method(originalRequest.method(), authenticate(originalRequest.body()))
.addHeader("signature", signature)
.build();
return chain.proceed(authenticatedRequest);
}
private RequestBody authenticate(final RequestBody body) {
return new RequestBody() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override
public long contentLength() throws IOException {
return -1;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink authSink = Okio.buffer(sink);
body.writeTo(sink);
String data = authSink.buffer().readUtf8();
signature = generateSignature(method, query, data, token);
authSink.close();
}
};
}
}
问题是,对于拦截器,结果在执行期间流式传输,所以我无法在处理之前获取签名值。
那么,is-there 一种在 header 中插入在 writeTo() 流方法中生成的签名值的聪明方法?
已更新 根据@Jesse 回答的代码。
private class SignatureInterceptor implements Interceptor {
@Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
String data = "";
if (originalRequest.body() != null) {
BufferedSink authSink = new Buffer();
originalRequest.body().writeTo(authSink);
data = authSink.buffer().readUtf8();
authSink.close();
}
Request authenticatedRequest = originalRequest.newBuilder()
.addHeader(HEADER_SIGNATURE, buildSignature(data))
.build();
return chain.proceed(authenticatedRequest);
}
}
您不需要创建自己的 RequestBody class;仅当您转换 body.
时才有必要将 writeTo
方法的内容移动到 intercept
中,这样您就可以在调用 proceed
之前计算签名。使用该签名添加 header.