自己撸一套验权,需要支持S3V4认证协议

1、核心代码很简单,就下面这些:

String Authorization = request.getHeader("Authorization");
        String xamzdate = request.getHeader("x-amz-date");
        String Host = request.getHeader("Host");


        log.info("S3协议方式,minio请求,url={},Authorization={},xamzdate={},Host={}",request.getRequestURI(),Authorization,xamzdate,Host);
        if(StringUtils.isBlank(Authorization) || StringUtils.isBlank(xamzdate) || StringUtils.isBlank(Host)){
            throw new HttpException(ErrorsEnum.AUTH_FAIL);
        }
        // 获取用户的key
        String[] Authorizations = Authorization.split(" ");
        String sha256 = Authorizations[0];
        String Credential = Authorizations[1];
        String SignedHeader = Authorizations[2];
        String Signature = Authorizations[3];
        if(!"AWS4-HMAC-SHA256".equals(sha256) || StringUtils.isBlank(Credential) || StringUtils.isBlank(SignedHeader) || StringUtils.isBlank(Signature)){
            throw new HttpException(ErrorsEnum.AUTH_FAIL);
        }
        // 获取用户名
        String ck = Credential.substring(Credential.indexOf("=")+1,Credential.indexOf("/"));
        String regin = Credential.split("/")[Credential.split("/").length-3];
        String servicename  = Credential.split("/")[Credential.split("/").length-2];

        

        // 计算auth
        // for a simple GET, we have no body so supply the precomputed 'empty' hash
        // 计算signedHeaders
        String[] SignedHeaders = SignedHeader.substring(SignedHeader.indexOf("=")+1,SignedHeader.length()-1).split(";");
        Map<String, String> headers = new HashMap<String, String>();
        for (String signedHeader : SignedHeaders) {
            headers.put(signedHeader,request.getHeader(signedHeader));
        }


       /* headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256);
        headers.put("x-amz-date",xamzdate);*/

        String url = host  + request.getRequestURI();
        URL endpointUrl = new URL(url);

        AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader(
                endpointUrl, request.getMethod(), servicename, regin);
        String authorization = signer.computeSignature(headers,
                null, // no query parameters
                headers.get("x-amz-content-sha256"),
                clientInfo.getClientKey(),
                clientInfo.getClientSecret());
        log.info("S3协议方式,签名校验,SignedHeaders={},authorization={}",headers.toString(),authorization);
        if(!Authorization.equals(authorization)){
            throw new HttpException(ErrorsEnum.AUTH_FAIL);
        }

但是里面的弯弯绕绕也太多了。

2、相关参考资料

签名原理:

header头的

Signature Calculations for the Authorization Header: Transferring Payload in a Single Chunk (AWS Signature Version 4) - Amazon Simple Storage Service

?拼接的

Authenticating Requests: Using Query Parameters (AWS Signature Version 4) - Amazon Simple Storage Service



处理Amazon S3对象 - AWS SDK for Java 2.x

aws-doc-sdk-examples/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java at main · awsdocs/aws-doc-sdk-examples · GitHub

Amazon S3 的 java sdk简单使用_aws-java-sdk-CSDN博客

Authenticating Requests: Using the Authorization Header (AWS Signature Version 4) - Amazon Simple Storage Service

Signature Calculations for the Authorization Header: Transferring Payload in Multiple Chunks (Chunked Upload) (AWS Signature Version 4) - Amazon Simple Storage Service

aws-doc-sdk-examples/javav2/example_code/s3/src/main/java/com/example/s3/PutObject.java at main · awsdocs/aws-doc-sdk-examples · GitHubGitHub - aws/aws-sdk-java-v2: The official AWS SDK for Java - Version 2Maven Repository: software.amazon.awssdk » aws-sdk-java » 2.21.42 (mvnrepository.com)

Maven Repository: software.amazon.awssdk » aws-sdk-java » 2.21.42 (mvnrepository.com)

API分片上传:

CreateMultipartUpload - Amazon Simple Storage Service

初始化分片上传的API接口_对象存储(OSS)-阿里云帮助中心 (aliyun.com)

3、配合使用

1、我们先搞个系统,导入pom

<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/aws-sdk-java -->
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>aws-sdk-java</artifactId>
    <version>2.21.42</version>
    <scope>provided</scope>
</dependency>

2、写个测试类:

package kf;

import com.alibaba.fastjson.JSONObject;

import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.math.BigInteger;
import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3ClientBuilder;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.endpoints.S3EndpointProvider;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3control.model.Credentials;

class testS3 {

    @Test
    void test() {
        S3Client s3 = S3Client.builder()
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("eda", "eda123456")))
                .region(Region.US_EAST_1)
                .endpointOverride(URI.create("http://localhost:8810/openapi/minio/"))
                .serviceConfiguration(S3Configuration.builder()
                        .pathStyleAccessEnabled(false)
                        .chunkedEncodingEnabled(false)
                        .build())
                .build();
        // 验证成功
//        s3.getObject(GetObjectRequest.builder().bucket("client_1").key("/20231201/2023120110242247663528991.jpg").build());
        // 验证上传
        s3.putObject(PutObjectRequest.builder().bucket("client_1").key("test.jpg").build(), RequestBody.fromFile(new File("D:\\pb\\Pictures\\test.jpg")));
//        System.out.println(s3.listBuckets());
    }




}

先测试获取文件和上传文件吧。

3、在自己需要验签的系统里,添加上面的核心代码,我这边是用切面处理的。

4、实现相关getObject、putObject等相关功能

底层可以自己打通,这样,相关的文件服务中台就ok了

ps:官方的demo里面是有bug的哦,请自己谨慎处理

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值