欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 22:01:35
...

官网文档: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 <a href="[email protected]">hm</a>
 * @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<String, String[]> 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中都是有的,不需要再依赖了)

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>com.vaadin.external.google</groupId>
          <artifactId>android-json</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.aliyun.oss</groupId>
      <artifactId>aliyun-sdk-oss</artifactId>
      <version>2.8.3</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-sts</artifactId>
      <version>3.0.0</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-core</artifactId>
      <version>3.5.0</version>
    </dependency>
    <!--		用java11接ossjdk缺少的包-->
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-core</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
      <version>1.1.1</version>
    </dependency>

注意:敲黑板啊,要测试回调必须把服务布到公网上。敲黑板啊,要测试回调必须把服务布到公网上。敲黑板啊,要测试回调必须把服务布到公网上。

相关标签: oss