根据OSS子账户获取STS的TOKEN

版权声明:本文为Fighter168原创文章,未经允许不得转载。 https://blog.csdn.net/fighterandknight/article/details/80517646

前言

目前来说,很多公司都使用者阿里云的资源,对象存储(OSS)就是其中一个我们经常使用的一个资源,在这个使用的过程中,如果我们想要做到一些安全管理(Security Token Service,简称 STS),以及资源的访问控制(Resource Access Management,简称 RAM),这里面也就是官方描述的RAM和STS。

如果你们平台对接很多个合作方,每个合作方又不想从阿里云中重新购买一个新的阿里云的oss,又想实现对每个合作方的资源的一个访问控制,以及权限管理,那么通过这种结合RAM和STS的方式,就非常容易解决这个问题。

阿里云的官方文档并未给出根据子账户的信息如何获取sts的token的例子,获取sts的token的流程有涉及到加签以及urlencode的处理,以及HMAC-SHA1算法的处理,所以这里面有一些坑,由于网上也没有找到详细的例子,官方也没给出例子,直是简单说了这个流程,所以自己倒腾了半天,才整理出来,并拿到生产上使用,下面结合代码说一下这个整体的实现流程。

实现逻辑

下面这个是官方给出的实现说明

这里写图片描述

根据子账户获取STS的TOKEN

生成sts的toke的工具类


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;



/** 
* @ClassName: GenTempOssUtil 
* @Description: 生成临时的oss信息
* @author wenhuixiang
* @date 2018年5月30日 下午4:35:10 
*  
*/
public class GenTempOssUtil {

    private static final String ENCODING = "UTF-8";

    private static final String STANDARD_DATE_FORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";  

    private final static Logger log = LoggerFactory.getLogger(HttpClientUtil.class);

    public static void main(String[] args)throws Exception {
        String accessId="你的accessId信息";
        String secretKey="你的secretKey信息";
        String arn="你的arn信息";
        genOssInfo(accessId, secretKey, arn);
    }


    /** 
    * @Title: genOssInfo 
    * @Description:  生产临时的 oss 信息
    * @param @param accessId 子账户的accessId
    * @param @param secretKey 子账户的secretKey
    * @param @param arn       对应子账户的权限信息等
    */
    public static String genOssInfo(String accessId,String secretKey,String arn){
        StringBuilder stringToSign=new StringBuilder();
        StringBuilder canonicalizedQueryString=new StringBuilder();
        StringBuilder reqBuilder=new StringBuilder();
        String resp=null;
        String uuid=UUID.randomUUID().toString();

        SimpleDateFormat sdf = new SimpleDateFormat(STANDARD_DATE_FORMAT_UTC);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String timestamp =sdf.format(new Date());

        stringToSign.append("GET&%2F&");

        try {
            canonicalizedQueryString.append("AccessKeyId="+URLEncoder.encode(accessId,ENCODING))
            .append("&Action="+URLEncoder.encode("AssumeRole",ENCODING))
            .append("&Format="+URLEncoder.encode("JSON",ENCODING))
            .append("&GET=")
            .append("&RoleArn="+URLEncoder.encode(arn,ENCODING))
            .append("&RoleSessionName="+URLEncoder.encode("client",ENCODING))
            .append("&SignatureMethod="+URLEncoder.encode("HMAC-SHA1",ENCODING))
            .append("&SignatureNonce="+URLEncoder.encode(uuid,ENCODING))
            .append("&SignatureVersion="+URLEncoder.encode("1.0",ENCODING))
            .append("&Timestamp="+URLEncoder.encode(timestamp,ENCODING))
            .append("&Version="+URLEncoder.encode("2015-04-01",ENCODING));

            stringToSign.append(URLEncoder.encode(canonicalizedQueryString.toString(),ENCODING));

            log.info("加签字符串:"+stringToSign.toString());
            String genHMAC = genHMAC(stringToSign.toString(),secretKey+"&");  

            reqBuilder.append("Format="+URLEncoder.encode("JSON",ENCODING))
            .append("&Version="+URLEncoder.encode("2015-04-01",ENCODING))
            .append("&AccessKeyId="+URLEncoder.encode(accessId,ENCODING))
            .append("&Signature="+URLEncoder.encode(genHMAC,ENCODING))
            .append("&SignatureMethod="+URLEncoder.encode("HMAC-SHA1",ENCODING))
            .append("&SignatureVersion="+URLEncoder.encode("1.0",ENCODING))
            .append("&SignatureNonce="+URLEncoder.encode(uuid,ENCODING))
            .append("&Timestamp="+URLEncoder.encode(timestamp,ENCODING))
            .append("&Action="+URLEncoder.encode("AssumeRole",ENCODING))
            .append("&GET=")
            .append("&RoleArn="+URLEncoder.encode(arn,ENCODING))
            .append("&RoleSessionName="+URLEncoder.encode("client",ENCODING));
        } catch (UnsupportedEncodingException e1) {
            resp="{\"msg\":\"获取oss信息参数编码转换异常\"}";
            log.error("获取oss信息参数编码转换异常",e1);
        }

        try {
            String reqUrl="https://sts.aliyuncs.com/?"+reqBuilder.toString();
            log.info("请求 获取临时的 oss 信息 地址:"+reqUrl);
            resp=HttpClientUtil.getRequest(reqUrl);
            JSONObject obj=JSON.parseObject(resp);
            obj.put("msg", "success");
            obj.put("desc", "success");
            resp=JSON.toJSONString(obj);
            log.info("阿里云返回的 oss 结果信息 :"+resp);
        } catch (Exception e) {
            JSONObject obj=new JSONObject();
            obj.put("msg", "failed");
            obj.put("desc", "获取临时的oss信息异常");
            resp=JSON.toJSONString(obj);
            log.error("获取临时的oss信息异常",e);
        }
     return resp;
    }


    /** 
     * 使用 HMAC-SHA1 签名方法对data进行签名 
     *  
     * @param data  被签名的字符串 
     * @param key   密钥      
     * @return      加密后的字符串 
     */  
    public static String genHMAC(String data, String key) {  
        byte[] result = null;  
        try {  
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称    
            SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);  
            //生成一个指定 Mac 算法 的 Mac 对象    
            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);  
            //用给定密钥初始化 Mac 对象    
            mac.init(signinKey);  
            //完成 Mac 操作     
            byte[] rawHmac = mac.doFinal(data.getBytes());  
            result = Base64.encodeBase64(rawHmac);  

        } catch (Exception e) {  
           log.error("HMAC-SHA1 加密失败",e);
        }  
        if (null != result) {  
            return new String(result);  
        } else {  
            return null;  
        }  
    }  
}

https请求的工具类


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/** 
* @ClassName: GenTempOssUtil 
* @Description: 类HttpClientUtil.java的实现描述:httpclient工具类
* @author wenhuixiang
* @date 2018年5月30日 下午4:35:10 
*  
*/
public class HttpClientUtil {

    public static final String RETURN_CODE_FAIL = "request_fail";
    private final static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private static final int timeout = 30000;
    /**
     * 每个主机最大连接数
     */
    private static final int maxConnectionsPerHost = 20;
    /**
     * 最大总共连接数
     */
    private static final int maxTotalConnection = 100;
    private static final String encoding = "UTF-8";

    private HttpClientUtil() {
    }

    /**
     * post请求
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 返回结果
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static String postRequest(String url, Map<String, String> params) {
        return postRequest(url, null, params);
    }

    /**
     * post请求
     *
     * @param url    请求地址
     * @param header 请求头
     * @param params 请求参数
     * @return 返回结果
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static String postRequest(String url, Map<String, String> header, Map<String, String> params) {
        String result = "";
        PostMethod postMethod = null;

        try {
            //创建连接
            HttpClient httpClient = new HttpClient(HttpClientUtilHolder.httpConnectionManager);
            // 设置编码
            httpClient.getParams().setContentCharset(encoding);
            httpClient.getParams().setHttpElementCharset(encoding);
            httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encoding);

            postMethod = new PostMethod(url);

            //设置头信息
            if (MapUtils.isNotEmpty(header)) {
                for (Map.Entry<String, String> entry : header.entrySet()) {
                    postMethod.setRequestHeader(entry.getKey(), entry.getValue());
                }
            }

            //设置参数
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            NameValuePair nameValuePair = null;
            Iterator iter = params.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                String key = (String) entry.getKey();
                String val = (String) entry.getValue();
                nameValuePair = new NameValuePair(key, val);
                list.add(nameValuePair);
            }
            NameValuePair[] data = list.toArray(new NameValuePair[list.size()]);
            postMethod.setRequestBody(data);

            //请求
            logger.info("=================httpclient发起请求");
            httpClient.executeMethod(postMethod);
            logger.info("=================httpclient请求结束");
            result = postMethod.getResponseBodyAsString();
            logger.info("httpclient请求结果:{}", result);
        } catch (Exception e) {
            logger.error("=================httpclient请求异常:", e);
            result = RETURN_CODE_FAIL;
        } finally {
            if (postMethod != null) {
                //释放连接
                postMethod.releaseConnection();
            }
        }
        return result;

    }

    /**
     * post请求-没有参数名,只有参数值
     *
     * @param url  请求地址
     * @param body 请求参数
     * @return 返回结果
     * @throws Exception
     */
    public static String postRequestOfNoParamName(String url, String body) {
        String result = "";
        PostMethod postMethod = null;

        try {
            //创建连接
            HttpClient httpClient = new HttpClient(HttpClientUtilHolder.httpConnectionManager);
            // 设置编码
            httpClient.getParams().setContentCharset(encoding);
            httpClient.getParams().setHttpElementCharset(encoding);
            httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encoding);

            postMethod = new PostMethod(url);
            postMethod.setRequestEntity(new StringRequestEntity(body, "", encoding));

            //请求
            httpClient.executeMethod(postMethod);
            result = postMethod.getResponseBodyAsString();
        } catch (Exception e) {
            logger.error("=================httpclient请求异常异常:", e);
            result = RETURN_CODE_FAIL;
        } finally {
            if (postMethod != null) {
                //释放连接
                postMethod.releaseConnection();
            }
        }
        return result;

    }

    public static String getRequest(String url) throws Exception {
        String result = "";
        GetMethod getMethod = null;
        try {
            //创建连接
            HttpClient httpClient = new HttpClient(HttpClientUtilHolder.httpConnectionManager);
            // 设置编码
            httpClient.getParams().setContentCharset(encoding);
            httpClient.getParams().setHttpElementCharset(encoding);
            httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encoding);

            getMethod = new GetMethod(url);
            //请求
            int statusCode = httpClient.executeMethod(getMethod);
            if (statusCode == HttpStatus.SC_OK) {
                result = getMethod.getResponseBodyAsString();
            } else {
                result = RETURN_CODE_FAIL;
            }
        } catch (Exception e) {
            logger.error("=================httpclient请求异常异常:", e);
            //          result = RETURN_CODE_FAIL;
            result = null;
            throw new Exception(e.getMessage(), e);
        } finally {
            if (getMethod != null) {
                //释放连接
                getMethod.releaseConnection();
            }
        }
        return result;

    }

    /**
     * 单例创建httpConnectionManager.
     */
    private static class HttpClientUtilHolder {
        private static HttpConnectionManager httpConnectionManager = initConnectionManager();

        private static HttpConnectionManager initConnectionManager() {
            logger.info("initConnectionManager");
            httpConnectionManager = new MultiThreadedHttpConnectionManager();
            HttpConnectionManagerParams params = httpConnectionManager.getParams();
            params.setConnectionTimeout(timeout);
            params.setSoTimeout(timeout);
            params.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost);
            params.setMaxTotalConnections(maxTotalConnection);
            return httpConnectionManager;
        }
    }

}

结果示例

这里写图片描述

使用获取到的token信息上传文件


    public static void main(String[] args) {
        String accessKeyId = "你获取到的accessKeyId";
        String accessKeySecret = "你获取到的secretKey";
        String securityToken = "你获取到的token";
        // 以杭州为例
        String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
        OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret, securityToken);

        ObjectMetadata meta = new ObjectMetadata();
        // 指定上传的内容类型。
        meta.setContentType("text/plain");

        UploadFileRequest fileReq=new UploadFileRequest("<yourBucketName>","<yourObjectName>");
        // 指定上传并发线程数,默认为1。
        fileReq.setTaskNum(5);
        // 指定上传的分片大小,从100KB到5GB,单位是Byte,默认为100K。
        fileReq.setPartSize(1 * 1024 * 1024);
        // 指定上传的本地文件,必选参数。
        fileReq.setUploadFile("C:\\Users\\Administrator\\Desktop\\123.png");
        //Object的元数据。
        fileReq.setObjectMetadata(meta);

        try {
            client.uploadFile(fileReq);
        } catch (Throwable e) {
            e.printStackTrace();
        }finally {
            if(client!=null) client.shutdown();
        }
    }

猜你喜欢

转载自blog.csdn.net/fighterandknight/article/details/80517646
sts