Prechádzať zdrojové kódy

通过配置文件来对oss进行授权,并将token、url放入redis,设置过期时间

yaobo 7 rokov pred
rodič
commit
573fe3a387

+ 111 - 57
src/main/java/cn/efunbox/audio/plugin/AliStsOssAuth.java

@@ -10,11 +10,13 @@ import com.aliyuncs.profile.IClientProfile;
 import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
 import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.data.redis.core.ValueOperations;
 import org.springframework.stereotype.Service;
 
 import java.net.URL;
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
@@ -27,19 +29,76 @@ public class AliStsOssAuth {
     @Autowired
     private StringRedisTemplate stringRedisTemplate;
 
-    private String accessKeyIdTemp = null;
-    private String accessKeySecretTemp = null;
-    private String securityTokenTemp = null;
-//
-//    public AliStsOssAuth(StringRedisTemplate stringRedisTemplate) {
-//        this.stringRedisTemplate = stringRedisTemplate;
-//    }
-
+    //是否开启oss资源的临时授权
+    @Value("${oss.auth.enable}")
+    private int auth_enable;
     // 目前只有"cn-hangzhou"这个region可用, 不要使用填写其他region的值
-    public final String REGION_CN_HANGZHOU = "cn-hangzhou";
+    @Value("${oss.auth.REGION_CN_HANGZHOU}")
+    private String REGION_CN_HANGZHOU;
     // 当前 STS API 版本
-    public final String STS_API_VERSION = "2015-04-01";
-    public AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret,
+    @Value("${oss.auth.STS_API_VERSION}")
+    private String STS_API_VERSION;
+    // 只有 RAM用户(子账号)才能调用 AssumeRole 接口
+    // 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
+    // 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
+    @Value("${oss.auth.accessKeyId}")
+    private String accessKeyId;
+    @Value("${oss.auth.accessKeySecret}")
+    private String accessKeySecret;
+    // AssumeRole API 请求参数: RoleArn, RoleSessionName, Policy, and DurationSeconds
+    // RoleArn 需要在 RAM 控制台上获取
+    @Value("${oss.auth.roleArn}")
+    private String roleArn;
+    // RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
+    // 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '_' 字母和数字等字符
+    // 具体规则请参考API文档中的格式要求
+    private String roleSessionName = "yifang_oss_audio";
+    // 如何定制你的policy?
+    private String policy = "{\n" +
+            "  \"Statement\": [\n" +
+            "    {\n" +
+            "      \"Action\": \"oss:*\",\n" +
+            "      \"Effect\": \"Allow\",\n" +
+            "      \"Resource\": \"*\"\n" +
+            "    }\n" +
+            "  ],\n" +
+            "  \"Version\": \"1\"\n" +
+            "}";
+
+    //原始完整路径:http://efunaudio.oss-cn-beijing.aliyuncs.com/audio/001/00103035/00103035018.mp3
+    //endpoint,如"oss-cn-beijing.aliyuncs.com"
+    @Value("${oss.auth.endpoint}")
+    private String endpoint;
+    //bucket名称,如"efunaudio"
+    @Value("${oss.auth.bucketName}")
+    String bucketName;
+    //url授权链接的过期时间
+    @Value("${oss.auth.url_expiration}")
+    long urlExpiration;
+//    //url的可以,如"audio/001/00103035/00103035018.mp3"
+//    String key = "audio/001/00103035/00103035018.mp3";
+
+    private String accessKeyIdRole = null;
+    private String accessKeySecretRole = null;
+    private String securityTokenRole = null;
+
+    private final String accessKeyIdRoleSession = "OSS_AUTH_accessKeyIdRole";
+    private final String accessKeySecretRoleSession = "OSS_AUTH_accessKeySecretRole";
+    private final String securityTokenRoleSession = "OSS_AUTH_securityTokenRole";
+    private final String urlAuthSession = "OSS_AUTH_URL_";
+
+    /**
+     * 向阿里申请下一步操作的token
+     * @param accessKeyId
+     * @param accessKeySecret
+     * @param roleArn
+     * @param roleSessionName
+     * @param policy
+     * @param protocolType
+     * @return AssumeRoleResponse
+     * @throws ClientException
+     */
+    private AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret,
                                          String roleArn, String roleSessionName, String policy,
                                          ProtocolType protocolType) throws ClientException {
         try {
@@ -62,42 +121,35 @@ public class AliStsOssAuth {
         }
     }
 
-    public void Auth(){
-        // 只有 RAM用户(子账号)才能调用 AssumeRole 接口
-        // 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
-        // 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
-        String accessKeyId = "LTAIwHeZreDzNDtR";
-        String accessKeySecret = "gCTp82PM7B8liUrNlHqfLTQQTKLSAe";
-        // AssumeRole API 请求参数: RoleArn, RoleSessionName, Policy, and DurationSeconds
-        // RoleArn 需要在 RAM 控制台上获取
-        String roleArn = "acs:ram::30370391:role/audioauth";
-        // RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
-        // 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '_' 字母和数字等字符
-        // 具体规则请参考API文档中的格式要求
-        String roleSessionName = "alice-001";
-        // 如何定制你的policy?
-        String policy = "{\n" +
-                "  \"Statement\": [\n" +
-                "    {\n" +
-                "      \"Action\": \"oss:*\",\n" +
-                "      \"Effect\": \"Allow\",\n" +
-                "      \"Resource\": \"*\"\n" +
-                "    }\n" +
-                "  ],\n" +
-                "  \"Version\": \"1\"\n" +
-                "}";
+    /**
+     * 对oss的资源url进行临时访问授权
+     * @param url
+     * @return
+     */
+    public String AuthUrl(String url){
+        if(auth_enable<1){
+            return url;
+        }
+        String[] arr = url.split(endpoint+"/");
+        if(arr==null || arr.length<2){
+            System.out.println("fail to split url");
+            return url;
+        }
+        String key = arr[1];
         // 此处必须为 HTTPS
         ProtocolType protocolType = ProtocolType.HTTPS;
         try {
-            stringRedisTemplate.opsForValue().set("aaa", "111");
-            System.out.println(stringRedisTemplate.opsForValue().get("aaa"));
             ValueOperations valueOperations = stringRedisTemplate.opsForValue();
-            if(valueOperations.get("accessKeyIdTemp")!=null
-                    && valueOperations.get("accessKeySecretTemp")!=null
-                    && valueOperations.get("securityTokenTemp")!=null ){
-                accessKeyIdTemp = valueOperations.get("accessKeyIdTemp").toString();
-                accessKeySecretTemp = valueOperations.get("accessKeySecretTemp").toString();
-                securityTokenTemp = valueOperations.get("securityTokenTemp").toString();
+            if(valueOperations.get(urlAuthSession+key)!=null){
+                url = valueOperations.get(urlAuthSession+key).toString();
+                return url;
+            }
+            if(valueOperations.get(accessKeyIdRoleSession)!=null
+                    && valueOperations.get(accessKeySecretRoleSession)!=null
+                    && valueOperations.get(securityTokenRoleSession)!=null ){
+                accessKeyIdRole = valueOperations.get(accessKeyIdRoleSession).toString();
+                accessKeySecretRole = valueOperations.get(accessKeySecretRoleSession).toString();
+                securityTokenRole = valueOperations.get(securityTokenRoleSession).toString();
             }else{
                 AssumeRoleResponse response = assumeRole(accessKeyId, accessKeySecret,
                         roleArn, roleSessionName, policy, protocolType);
@@ -107,25 +159,26 @@ public class AliStsOssAuth {
                 System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
                 System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
 
-                accessKeyIdTemp = response.getCredentials().getAccessKeyId();
-                accessKeySecretTemp = response.getCredentials().getAccessKeySecret();
-                securityTokenTemp = response.getCredentials().getSecurityToken();
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+                Date dateExp = sdf.parse(response.getCredentials().getExpiration());
+                long expiration = dateExp.getTime() + 8*3600*1000;
+                long curTime = new Date().getTime();
+                accessKeyIdRole = response.getCredentials().getAccessKeyId();
+                accessKeySecretRole = response.getCredentials().getAccessKeySecret();
+                securityTokenRole = response.getCredentials().getSecurityToken();
 
-                valueOperations.set("accessKeyIdTemp", accessKeyIdTemp, 20L, TimeUnit.SECONDS);
-                valueOperations.set("accessKeySecretTemp", accessKeySecretTemp, 20L, TimeUnit.SECONDS);
-                valueOperations.set("securityTokenTemp", securityTokenTemp, 20L, TimeUnit.SECONDS);
+                valueOperations.set(accessKeyIdRoleSession, accessKeyIdRole, expiration-curTime, TimeUnit.MILLISECONDS);
+                valueOperations.set(accessKeySecretRoleSession, accessKeySecretRole, expiration-curTime, TimeUnit.MILLISECONDS);
+                valueOperations.set(securityTokenRoleSession, securityTokenRole, expiration-curTime, TimeUnit.MILLISECONDS);
             }
 
-            //原始完整路径:http://efunaudio.oss-cn-beijing.aliyuncs.com/audio/001/00103035/00103035018.mp3
-            String endpoint = "oss-cn-beijing.aliyuncs.com";
-            OSSClient client = new OSSClient(endpoint, accessKeyIdTemp, accessKeySecretTemp, securityTokenTemp);
-            String bucketName = "efunaudio";
-            String key = "audio/001/00103035/00103035018.mp3";
             // 设置URL过期时间为1小时
-            Date expiration = new Date(new Date().getTime() + 3600 * 1000);
+            Date expiration = new Date(new Date().getTime() + urlExpiration * 1000);
             // 生成URL
-            URL url = client.generatePresignedUrl(bucketName, key, expiration);
-            System.out.println(url.toString());
+            OSSClient client = new OSSClient(endpoint, accessKeyIdRole, accessKeySecretRole, securityTokenRole);
+            URL urlAuth = client.generatePresignedUrl(bucketName, key, expiration);
+            url = urlAuth.toString();
+            valueOperations.set(urlAuthSession+key, url, urlExpiration, TimeUnit.SECONDS);
         } catch (ClientException e) {
             System.out.println("Failed to get a token.");
             System.out.println("Error code: " + e.getErrCode());
@@ -133,5 +186,6 @@ public class AliStsOssAuth {
         } catch (Exception e){
             System.out.println("Error message: " + e.getMessage());
         }
+        return url;
     }
 }

+ 26 - 1
src/main/resources/application.properties

@@ -40,4 +40,29 @@ spring.redis.pool.max-idle=8
 # 连接池中的最小空闲连接
 spring.redis.pool.min-idle=0
 # 连接超时时间(毫秒)
-spring.redis.timeout=0
+spring.redis.timeout=0
+
+
+########################################################
+### Alibaba OSS 资源临时授权 基本配置;
+########################################################
+#是否开启鉴权加密,1为是,0位否
+oss.auth.enable = 1
+#目前只有"cn-hangzhou"这个region可用, 不要使用填写其他region的值
+oss.auth.REGION_CN_HANGZHOU = cn-hangzhou
+#当前 STS API 版本
+oss.auth.STS_API_VERSION = 2015-04-01
+# 只有 RAM用户(子账号)才能调用 AssumeRole 接口
+# 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
+# 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
+oss.auth.accessKeyId = LTAIwHeZreDzNDtR
+oss.auth.accessKeySecret = gCTp82PM7B8liUrNlHqfLTQQTKLSAe
+# AssumeRole API 请求参数: RoleArn, RoleSessionName, Policy, and DurationSeconds
+# RoleArn 需要在 RAM 控制台上获取
+oss.auth.roleArn = acs:ram::30370391:role/audioauth
+#endpoint,如"oss-cn-beijing.aliyuncs.com"
+oss.auth.endpoint = oss-cn-beijing.aliyuncs.com
+#bucket名称,如"efunaudio"
+oss.auth.bucketName = efunaudio
+#url授权链接的过期时间
+oss.auth.url_expiration = 3600

+ 14 - 6
src/test/java/cn/efunbox/audio/AudioApplicationTests.java

@@ -12,6 +12,9 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.UUID;
 
 @RunWith(SpringJUnit4ClassRunner.class)
@@ -48,16 +51,21 @@ public class AudioApplicationTests {
 
 	@Test
 	public void aliAuth(){
-		// 保存字符串
+//		try {
+//			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+//			Date dateExp = sdf.parse("2017-10-12T04:01:32Z");
+//			long expiration = dateExp.getTime();
+//			long curTime = new Date().getTime();
+//		}catch (ParseException e){
+//			System.out.println(e.getMessage());
+//		}
+
+		// 测试redis保存字符串
 		stringRedisTemplate.opsForValue().set("aaa", "111");
 		Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
 		System.out.println(stringRedisTemplate.opsForValue().get("aaa"));
 
-//		AliStsServiceSample.Auth();
-//		AliStsOssAuth auth = new AliStsOssAuth(stringRedisTemplate);
-//		auth.Auth();
-
-		aliStsOssAuth.Auth();
+		String url = aliStsOssAuth.AuthUrl("http://efunaudio.oss-cn-beijing.aliyuncs.com/audio/001/00103035/00103035018.mp3");
 	}
 
 }