本文主要是介绍聊聊AsyncHttpClient的SignatureCalculator,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
序
本文主要研究一下AsyncHttpClient的SignatureCalculator
SignatureCalculator
org/asynchttpclient/SignatureCalculator.java
/*** Interface that allows injecting signature calculator into* {@link RequestBuilder} so that signature calculation and inclusion can* be added as a pluggable component.** @since 1.1*/
public interface SignatureCalculator {/*** Method called when {@link RequestBuilder#build} method is called.* Should first calculate signature information and then modify request* (using passed {@link RequestBuilder}) to add signature (usually as* an HTTP header).** @param requestBuilder builder that can be used to modify request, usually* by adding header that includes calculated signature. Be sure NOT to* call {@link RequestBuilder#build} since this will cause infinite recursion* @param request Request that is being built; needed to access content to* be signed*/void calculateAndAddSignature(Request request,RequestBuilderBase<?> requestBuilder);
}
SignatureCalculator定义了calculateAndAddSignature接口,它首先计算签名,然后添加到requestBuilder
OAuthSignatureCalculator
org/asynchttpclient/oauth/OAuthSignatureCalculator.java
/*** OAuth {@link SignatureCalculator} that delegates to {@link OAuthSignatureCalculatorInstance}s.*/
public class OAuthSignatureCalculator implements SignatureCalculator {private static final ThreadLocal<OAuthSignatureCalculatorInstance> INSTANCES = ThreadLocal.withInitial(() -> {try {return new OAuthSignatureCalculatorInstance();} catch (NoSuchAlgorithmException e) {throw new ExceptionInInitializerError(e);}});private final ConsumerKey consumerAuth;private final RequestToken userAuth;/*** @param consumerAuth Consumer key to use for signature calculation* @param userAuth Request/access token to use for signature calculation*/public OAuthSignatureCalculator(ConsumerKey consumerAuth, RequestToken userAuth) {this.consumerAuth = consumerAuth;this.userAuth = userAuth;}@Overridepublic void calculateAndAddSignature(Request request, RequestBuilderBase<?> requestBuilder) {try {INSTANCES.get().sign(consumerAuth, userAuth, request, requestBuilder);} catch (InvalidKeyException e) {throw new IllegalArgumentException("Failed to compute a valid key from consumer and user secrets", e);}}
}
OAuthSignatureCalculator实现了SignatureCalculator接口,其calculateAndAddSignature方法使用了OAuthSignatureCalculatorInstance的sign方法
sign
org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java
public void sign(ConsumerKey consumerAuth, RequestToken userAuth, Request request, RequestBuilderBase<?> requestBuilder) throws InvalidKeyException {String nonce = generateNonce();long timestamp = generateTimestamp();sign(consumerAuth, userAuth, request, requestBuilder, timestamp, nonce);}void sign(ConsumerKey consumerAuth, RequestToken userAuth, Request request, RequestBuilderBase<?> requestBuilder, long timestamp, String nonce) throws InvalidKeyException {String percentEncodedNonce = Utf8UrlEncoder.percentEncodeQueryElement(nonce);String signature = calculateSignature(consumerAuth, userAuth, request, timestamp, percentEncodedNonce);String headerValue = constructAuthHeader(consumerAuth, userAuth, signature, timestamp, percentEncodedNonce);requestBuilder.setHeader(HttpHeaderNames.AUTHORIZATION, headerValue);} String calculateSignature(ConsumerKey consumerAuth, RequestToken userAuth, Request request, long oauthTimestamp, String percentEncodedNonce) throws InvalidKeyException {StringBuilder sb = signatureBaseString(consumerAuth, userAuth, request, oauthTimestamp, percentEncodedNonce);ByteBuffer rawBase = StringUtils.charSequence2ByteBuffer(sb, UTF_8);byte[] rawSignature = digest(consumerAuth, userAuth, rawBase);// and finally, base64 encoded... phew!return Base64.encode(rawSignature);}
OAuthSignatureCalculatorInstance的sign方法先生成nonce及timestamp,然后通过calculateSignature计算signature,再通过constructAuthHeader计算headerValue,最后设置到requestBuilder的名为authorization的header
executeSignatureCalculator
org/asynchttpclient/RequestBuilderBase.java
private RequestBuilderBase<?> executeSignatureCalculator() {if (signatureCalculator == null)return this;// build a first version of the request, without signatureCalculator in playRequestBuilder rb = new RequestBuilder(this.method);// make copy of mutable collections so we don't risk affecting// original RequestBuilder// call setFormParams first as it resets other fieldsif (this.formParams != null)rb.setFormParams(this.formParams);if (this.headers != null)rb.headers.add(this.headers);if (this.cookies != null)rb.setCookies(this.cookies);if (this.bodyParts != null)rb.setBodyParts(this.bodyParts);// copy all other fields// but rb.signatureCalculator, that's the whole point hererb.uriEncoder = this.uriEncoder;rb.queryParams = this.queryParams;rb.uri = this.uri;rb.address = this.address;rb.localAddress = this.localAddress;rb.byteData = this.byteData;rb.compositeByteData = this.compositeByteData;rb.stringData = this.stringData;rb.byteBufferData = this.byteBufferData;rb.streamData = this.streamData;rb.bodyGenerator = this.bodyGenerator;rb.virtualHost = this.virtualHost;rb.proxyServer = this.proxyServer;rb.realm = this.realm;rb.file = this.file;rb.followRedirect = this.followRedirect;rb.requestTimeout = this.requestTimeout;rb.rangeOffset = this.rangeOffset;rb.charset = this.charset;rb.channelPoolPartitioning = this.channelPoolPartitioning;rb.nameResolver = this.nameResolver;Request unsignedRequest = rb.build();signatureCalculator.calculateAndAddSignature(unsignedRequest, rb);return rb;}
executeSignatureCalculator会执行signatureCalculator.calculateAndAddSignature(unsignedRequest, rb)
build
org/asynchttpclient/RequestBuilderBase.java
public Request build() {updateCharset();RequestBuilderBase<?> rb = executeSignatureCalculator();Uri finalUri = rb.computeUri();// make copies of mutable internal collectionsList<Cookie> cookiesCopy = rb.cookies == null ? Collections.emptyList() : new ArrayList<>(rb.cookies);List<Param> formParamsCopy = rb.formParams == null ? Collections.emptyList() : new ArrayList<>(rb.formParams);List<Part> bodyPartsCopy = rb.bodyParts == null ? Collections.emptyList() : new ArrayList<>(rb.bodyParts);return new DefaultRequest(rb.method,finalUri,rb.address,rb.localAddress,rb.headers,cookiesCopy,rb.byteData,rb.compositeByteData,rb.stringData,rb.byteBufferData,rb.streamData,rb.bodyGenerator,formParamsCopy,bodyPartsCopy,rb.virtualHost,rb.proxyServer,rb.realm,rb.file,rb.followRedirect,rb.requestTimeout,rb.readTimeout,rb.rangeOffset,rb.charset,rb.channelPoolPartitioning,rb.nameResolver);}
RequestBuilderBase的build方法会执行executeSignatureCalculator
小结
SignatureCalculator定义了calculateAndAddSignature接口,它首先计算签名,然后添加到requestBuilder;它有个实现类为OAuthSignatureCalculator;RequestBuilderBase的build方法会执行executeSignatureCalculator。
这篇关于聊聊AsyncHttpClient的SignatureCalculator的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!