retrofit 服务自定义签名认证

0 条评论

因为用在一个不是特别主流的方案里,所以还是记录下。服务所有的请求通过 form data 格式传输,然后每一次的请求都需要使用服务端给客户端分配的密钥对请求参数进行签名,

直接基于 OkHttpClient 扩展 Interceptor 实现,如下:

  1. public class SignInterceptor implements Interceptor {
  2.     private final Mac mac;
  3.     private final String clientId;
  4.     public SignInterceptor(String clientId, String clientKey) throws NoSuchAlgorithmException, InvalidKeyException {
  5.         this.clientId = clientId;
  6.         byte[] key = clientKey.getBytes(StandardCharsets.UTF_8);
  7.         SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
  8.         this.mac = Mac.getInstance("HmacSHA256");
  9.         this.mac.init(keySpec);
  10.     }
  11.     @Override
  12.     public Response intercept(Chain chain) throws IOException {
  13.         Request request = chain.request();
  14.         RequestBody requestBody = request.body();
  15.         if (requestBody instanceof FormBody) {
  16.             FormBody originFormBody = (FormBody) requestBody;
  17.             FormBody.Builder formBody = new FormBody.Builder();
  18.             List fields = new ArrayList<>(originFormBody.size());
  19.             int size = originFormBody.size();
  20.             for (int i = 0; i < size; i++) {
  21.                 String encodedName = originFormBody.encodedName(i);
  22.                 String encodedValue = originFormBody.encodedValue(i);
  23.                 fields.add(encodedName + "=" + encodedValue);
  24.                 formBody.addEncoded(encodedName, encodedValue);
  25.             }
  26.             Collections.sort(fields);
  27.             String baseString = String.join("&", fields);
  28.             Base64.Encoder encoder = Base64.getEncoder();
  29.             String signature = encoder.encodeToString(
  30.                     mac.doFinal(baseString.getBytes(StandardCharsets.UTF_8)));
  31.             formBody.add("clientId", this.clientId);
  32.             formBody.add("signature", signature);
  33.             request = request.newBuilder()
  34.                     .method(request.method(),
  35.                             formBody.build())
  36.                     .build();
  37.         }
  38.         return chain.proceed(request);
  39.     }
  40. }

然后在构建服务的时候添加进去:

  1. Retrofit retrofit = new Retrofit.Builder()
  2.         .baseUrl("http://127.0.0.1:8080/")
  3.         .addConverterFactory(new FormBodyConverterFactory())
  4.         .addConverterFactory(GsonConverterFactory.create())
  5.         .client(new OkHttpClient.Builder()
  6.                 .addInterceptor(new SignInterceptor("dev", "key"))
  7.                 .build())
  8.         .build();

相关日志 Relate Posts

收藏与分享 : Twitter | Facebook | 微博 | 人人 | Google+ | PDF

发表留言(Ctrl+Enter提交)