oss服务端签名客户端上传并设置服务端回调,服务端对回调进行验证

官网文档:https://help.aliyun.com/document_detail/31989.html?spm=a2c4g.11186623.2.14.292d15a6Afw15W#reference-b3p-cyw-wdb

官网JavaDemo:https://gosspublic.alicdn.com/images/AppCallbackServer.zip?spm=a2c4g.11186623.2.18.77b572c1XY3Eux&file=AppCallbackServer.zip

我的项目是使用的springboot,将官网的项目部分代码复制进来后测试,发现获取ossCallBody()这个方法获取不到值,遂,改造。代码如下。

package com.imiros.imiros.oss;

import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.tomcat.util.buf.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;

/**
 * TODO
 *
 * @author hm
 * @version 1.0.0, 05-29-2019
 */
@RestController
@RequestMapping("oss")
@SuppressWarnings(value={"all"})
public class OssController {

  static final Logger logger = LoggerFactory.getLogger(OssController.class);
  static final String endpoint = "sts.cn-hangzhou.aliyuncs.com";
  static final String accessKeyId = "";
  static final String accessKeySecret = "";
  static final String roleArn = "";
  static final String roleSessionName = "";
    //以上账号信息请使用自己的阿里云相关信息。

  @RequestMapping("getToken")
  public String getToken() {
    JSONObject jsonObject = new JSONObject();
    String policy = "{\n" +
      "    \"Version\": \"1\", \n" +
      "    \"Statement\": [\n" +
      "        {\n" +
      "            \"Action\": [\n" +
      "                \"oss:*\"\n" +
      "            ], \n" +
      "            \"Resource\": [\n" +
      "                \"acs:oss:*:*:*\" \n" +
      "            ], \n" +
      "            \"Effect\": \"Allow\"\n" +
      "        }\n" +
      "    ]\n" +
      "}";
    try {
      // 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
      DefaultProfile.addEndpoint("", "", "Sts", endpoint);
      // 构造default profile(参数留空,无需添加region ID)
      IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
      // 用profile构造client
      DefaultAcsClient client = new DefaultAcsClient(profile);
      final AssumeRoleRequest request = new AssumeRoleRequest();
      request.setMethod(MethodType.POST);
      request.setRoleArn(roleArn);
      request.setRoleSessionName(roleSessionName);
      // Optional
      request.setPolicy(policy);
      final AssumeRoleResponse response = client.getAcsResponse(request);
      jsonObject.put("Expiration", response.getCredentials().getExpiration());
      jsonObject.put("AccessKeyId", response.getCredentials().getAccessKeyId());
      jsonObject.put("AccessKeySecret", response.getCredentials().getAccessKeySecret());
      jsonObject.put("SecurityToken", response.getCredentials().getSecurityToken());
      jsonObject.put("StatusCode", "200");
      System.out.println(response.getCredentials());
    } catch (ClientException e) {
      jsonObject.put("ErrorCode", e.getErrCode());
      jsonObject.put("StatusCode", "500");
      jsonObject.put("ErrorMessage", e.getErrMsg());
    }
    logger.info("获取OSS的STS凭证响应信息 : " + jsonObject.toString());
    return jsonObject.toString();
  }

  @RequestMapping(value = "callback")
  public String upload(HttpServletRequest request, String filename) {
    String ossCallbackBody = "";
    JSONObject jsonObject = new JSONObject();
    Map map = request.getParameterMap();
    if (map.size() != 0) {
      for (String key : map.keySet()) {
        ossCallbackBody += key + "=" + StringUtils.join(map.get(key)) + "&";
      }
      ossCallbackBody = ossCallbackBody.substring(0, ossCallbackBody.length() - 1);
    }
    logger.info("ossCallbackBody:" + ossCallbackBody);
    boolean ret = VerifyOSSCallbackRequest(request, ossCallbackBody);
    if (ret) {
      jsonObject.put("filename", filename);
      jsonObject.put("Status", "OK");
    } else {
      jsonObject.put("Status", "verify not ok");
    }
    logger.info("OSS的回调响应 :" + jsonObject.toString());
    return jsonObject.toString();
  }

  protected boolean VerifyOSSCallbackRequest(HttpServletRequest request, String ossCallbackBody) {
    boolean ret = false;
    String autorizationInput = new String(request.getHeader("Authorization"));
    String pubKeyInput = request.getHeader("x-oss-pub-key-url");
    byte[] authorization = BinaryUtil.fromBase64String(autorizationInput);
    byte[] pubKey = BinaryUtil.fromBase64String(pubKeyInput);
    String pubKeyAddr = new String(pubKey);
    if (!pubKeyAddr.startsWith("http://gosspublic.alicdn.com/") && !pubKeyAddr
      .startsWith("https://gosspublic.alicdn.com/")) {
      System.out.println("pub key addr must be oss addrss");
      return false;
    }
    String retString = executeGet(pubKeyAddr);
    retString = retString.replace("-----BEGIN PUBLIC KEY-----", "");
    retString = retString.replace("-----END PUBLIC KEY-----", "");
    String queryString = request.getQueryString();
    String uri = request.getRequestURI();
    String decodeUri = null;
    try {
      decodeUri = java.net.URLDecoder.decode(uri, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    String authStr = decodeUri;
    if (queryString != null && !queryString.equals("")) {
      authStr += "?" + queryString;
    }
    authStr += "\n" + ossCallbackBody;
    ret = doCheck(authStr, authorization, retString);
    logger.info("------authStr:" + authStr);
    logger.info("------pubKeyAddr:" + pubKeyAddr);
    logger.info("------authorization:" + authorization);
    logger.info("------retString:" + retString);
    return ret;
  }

  public String executeGet(String url) {
    BufferedReader in = null;

    String content = null;
    try {
      // 定义HttpClient
      @SuppressWarnings("resource")
      DefaultHttpClient client = new DefaultHttpClient();
      // 实例化HTTP方法
      HttpGet request = new HttpGet();
      request.setURI(new URI(url));
      HttpResponse response = client.execute(request);

      in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
      StringBuffer sb = new StringBuffer("");
      String line = "";
      String NL = System.getProperty("line.separator");
      while ((line = in.readLine()) != null) {
        sb.append(line + NL);
      }
      in.close();
      content = sb.toString();
    } catch (Exception e) {
    } finally {
      if (in != null) {
        try {
          in.close();// 最后要关闭BufferedReader
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
      return content;
    }
  }

  public static boolean doCheck(String content, byte[] sign, String publicKey) {
    try {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      byte[] encodedKey = BinaryUtil.fromBase64String(publicKey);
      PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
      java.security.Signature signature = java.security.Signature.getInstance("MD5withRSA");
      signature.initVerify(pubKey);
      signature.update(content.getBytes());
      boolean bverify = signature.verify(sign);
      return bverify;

    } catch (Exception e) {
      e.printStackTrace();
    }

    return false;
  }

}

需要的pom文件如下:(我用的是java11,看下面的注释,java11缺少的那部分包可以不需要导入。在java8中都是有的,不需要再依赖了)


      org.springframework.boot
      spring-boot-starter
    
    
      org.springframework.boot
      spring-boot-starter-web
    
    
      org.springframework.boot
      spring-boot-starter-test
      test
      
        
          com.vaadin.external.google
          android-json
        
      
    
    
      com.aliyun.oss
      aliyun-sdk-oss
      2.8.3
    
    
      com.aliyun
      aliyun-java-sdk-sts
      3.0.0
    
    
      com.aliyun
      aliyun-java-sdk-core
      3.5.0
    
    
    
      javax.xml.bind
      jaxb-api
      2.3.0
    
    
      com.sun.xml.bind
      jaxb-impl
      2.3.0
    
    
      com.sun.xml.bind
      jaxb-core
      2.3.0
    
    
      javax.activation
      activation
      1.1.1
    

注意:敲黑板啊,要测试回调必须把服务布到公网上。敲黑板啊,要测试回调必须把服务布到公网上。敲黑板啊,要测试回调必须把服务布到公网上。也可以使用评论所说的方法。

你可能感兴趣的:(后端)