一、写在前面
一个常见的场景是:需要让客户端来上传图片,面临的安全性问题。给与客户端永久凭据无疑是很大风险的,我们还可以选择“给予一个临时凭据,这个凭据关联到一个 授权的用户,我们可以随时停用和修改这个用户具有的权限”
Minio提供了STS 的方式来实现这个方法。
MinIO安全令牌服务(STS)API允许应用程序生成用于访问MinIO部署的临时凭据。参考https://min.io/docs/minio/linux/developers/security-token-service.html
整体方案是:
- Minio服务器的web页面创建一个 用户和策略
- Java应用服务通过 使用上面的用户信息 使用 API 可取得临时的 凭据 token
- 将 临时凭据 给到前端 Web,或者App
- 前端使用 临时凭据 和 js API 等,进行对象的上传,获得等。
二、部署和启动 Minio
2.1、安装
wget https://dl.min.io/server/minio/release/linux-amd64//minio
chmod +x minio
这时可使用 ./minio 了
2.2 启动
./minio server /mnt/data
注意:/mnt/data 是图片存放位置
为了使用方便,自己写个启动脚本
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=password
export MINIO_REGION=***-beijing-2
nohup ./minio server /mnt/data &
*注意:
- MINIO_ROOT_USER 你的管理员账号
- MINIO_ROOT_PASSWORD 你的管理员密码
- MINIO_REGION 是你指定的区域名
2.3 访问控制台
打开网页: http://你的机器:9000
三、配置临时凭据相关的设置项
我采用 web控制台页面来设置,比较方便。
打开 http://你的机器:9000 , 登录进去
3.1、登录控制面板,创建策略
图片中编号3: 填写个策略名
图片中编号4: 填写 json 格式描述的具体策略
可以按我的填,下面的json描述了一个可读,写,删,获得桶位置的策略。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
3.2、创建用户,绑定策略
图片中编号4:填写一个 用户名(随便填,记下来要用)
图片中编号5:填写一个 密码(随便填,记下来要用)
图片中编号6:打钩选一个策略,就是我们上面 创建的策略 勾选上。
四、通过Java 获得凭据并上传和获得上传后的URL
1、创一个Maven项目
2、 加入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.3</version>
</dependency>
3、取得临时凭据
一些静态变量定义
//服务所在ip地址和端口
public static final String ENDPOINT = "http://10.0.0.102:9000/";
//mc的用户名
public static final String A***ESS_KEY_***PANY = "sts-user";
//mc的密码
public static final String SECRET_KEY_***PANY = "sts-password";
//aws服务端点
public static final String REGION = "***-beijing-2";
//上传的bucket名
public static final String BUCKET = "test";
//授权策略,允许访问名为bucket的桶的目录
public static final String ROLE_ARN = "arn:aws:s3:::test/*";
public static final String ROLE_SESSION_NAME = "anysession";
//定义策略,可进行二次限定
public static final String POLICY_GET_AND_PUT = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Action\": [\n" +
" \"s3:GetObject\",\n" +
" \"s3:GetBucketLocation\",\n" +
" \"s3:PutObject\"\n" +
" ],\n" +
" \"Resource\": [\n" +
" \"arn:aws:s3:::test/*\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
得到 临时凭据
/**
* 得到 临时凭据
*/
private static Credentials getCredentials() throws NoSuchAlgorithmException {
int durationSeconds = 360000;//秒
//创建签名对象
AssumeRoleProvider provider = new AssumeRoleProvider(
ENDPOINT,
A***ESS_KEY_***PANY,
SECRET_KEY_***PANY,
durationSeconds,//默认3600秒失效,设置小于这个就是3600,大于3600就实际值
POLICY_GET_AND_PUT,
REGION,
ROLE_ARN,
ROLE_SESSION_NAME,
null,
null);
Date expirationDate = DateUtil.getDateByAddMinute(new Date(), durationSeconds / 60);
/**
* 打印provider签名属性
*/
System.out.println("sessionToken=" + provider.fetch().sessionToken());
System.out.println("a***essKey=" + provider.fetch().a***essKey());
System.out.println("secretKey=" + provider.fetch().secretKey());
System.out.println("isExpired=" + provider.fetch().isExpired());
System.out.println("expirationDate=" + DateUtil.getDateTimeFormat(expirationDate));
Credentials credentials = provider.fetch();
String sessionToken = provider.fetch().sessionToken();
String a***essKey = provider.fetch().a***essKey();
String secretKey = provider.fetch().secretKey();
return credentials;
}
// 上传
private static void putObject(File file, String objectName, Credentials credentials) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
StaticProvider staticProvider = new StaticProvider(credentials.a***essKey(), credentials.secretKey(), credentials.sessionToken());
MinioClient minioClient = MinioClient.builder().endpoint(ENDPOINT).credentialsProvider(staticProvider).build();
//这个objectName的值是经过上面的policy授权的
FileInputStream fileInputStream = new FileInputStream(file);
minioClient.putObject(PutObjectArgs.builder().bucket(BUCKET)
.object(objectName)
.contentType("image/jpg")
.stream(fileInputStream, fileInputStream.available(), -1).build());
}
// 获得一个 可过期的 URL
private static String getObjectUrl(String objectName2,Credentials credentials) throws ErrorResponseException, InsufficientDataException, InternalException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException, ServerException {
StaticProvider staticProvider = new StaticProvider(credentials.a***essKey(), credentials.secretKey(), credentials.sessionToken());
MinioClient minioClient = MinioClient.builder().endpoint(ENDPOINT).credentialsProvider(staticProvider).build();
String url =
minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(BUCKET)
.object(objectName2)
.expiry(2, TimeUnit.HOURS) //过期时间
//.extraQueryParams(reqParams)
.build());
System.out.println(url);
return url;
}
五、参考:
https://blog.csdn.***/yilvqingtai/article/details/126059858https://min.io/docs/minio/linux/developers/java/API.html