361 changed files with 2473 additions and 3895 deletions
@ -0,0 +1,53 @@ |
|||||
|
package org.dromara.common.oss.factory; |
||||
|
|
||||
|
import com.aliyuncs.DefaultAcsClient; |
||||
|
import com.aliyuncs.auth.sts.AssumeRoleRequest; |
||||
|
import com.aliyuncs.auth.sts.AssumeRoleResponse; |
||||
|
import com.aliyuncs.exceptions.ClientException; |
||||
|
import com.aliyuncs.http.MethodType; |
||||
|
import com.aliyuncs.profile.DefaultProfile; |
||||
|
import com.aliyuncs.profile.IClientProfile; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.dromara.common.oss.core.OssClient; |
||||
|
import org.dromara.common.sdk.cloudapi.storage.CredentialsToken; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @auther wuyuan |
||||
|
* @data 2025/2/15 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class AliyunOss { |
||||
|
|
||||
|
public static CredentialsToken getCredentials( OssClient client) { |
||||
|
try { |
||||
|
String regionId = ""; |
||||
|
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
|
||||
|
DefaultProfile.addEndpoint(regionId, "Sts", "sts.cn-hangzhou.aliyuncs.com"); |
||||
|
// 添加endpoint。适用于Java SDK 3.12.0以下版本。
|
||||
|
// DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
|
||||
|
// 构造default profile。
|
||||
|
IClientProfile profile = DefaultProfile.getProfile(regionId, client.getOssProperties().getAccessKey(), client.getOssProperties().getSecretKey()); |
||||
|
// 构造client。
|
||||
|
DefaultAcsClient ascClient = new DefaultAcsClient(profile); |
||||
|
AssumeRoleRequest request = new AssumeRoleRequest(); |
||||
|
// 适用于Java SDK 3.12.0及以上版本。
|
||||
|
request.setSysMethod(MethodType.POST); |
||||
|
// 适用于Java SDK 3.12.0以下版本。
|
||||
|
//request.setMethod(MethodType.POST);
|
||||
|
request.setRoleArn(client.getOssProperties().getRoleArn()); |
||||
|
request.setRoleSessionName(client.getOssProperties().getRoleSessionName()); |
||||
|
request.setDurationSeconds(client.getOssProperties().getExpire()); |
||||
|
AssumeRoleResponse response = ascClient.getAcsResponse(request); |
||||
|
|
||||
|
return new CredentialsToken(response.getCredentials().getAccessKeyId(), response.getCredentials().getAccessKeySecret(), response.getCredentials().getSecurityToken(), client.getOssProperties().getExpire()); |
||||
|
} catch (ClientException e) { |
||||
|
log.debug("Failed to obtain sts."); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
package org.dromara.common.oss.factory; |
||||
|
|
||||
|
|
||||
|
import org.dromara.common.oss.core.OssClient; |
||||
|
import org.dromara.common.sdk.cloudapi.storage.CredentialsToken; |
||||
|
import org.dromara.common.sdk.cloudapi.storage.OssTypeEnum; |
||||
|
|
||||
|
import java.io.InputStream; |
||||
|
import java.net.URL; |
||||
|
|
||||
|
/** |
||||
|
* @author sean |
||||
|
* @version 0.3 |
||||
|
* @date 2021/12/23 |
||||
|
*/ |
||||
|
public interface IOssService { |
||||
|
|
||||
|
/** |
||||
|
* Get temporary credentials. |
||||
|
* @return |
||||
|
*/ |
||||
|
CredentialsToken getCredentials(OssClient client); |
||||
|
|
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package org.dromara.common.oss.factory; |
||||
|
|
||||
|
import com.amazonaws.auth.AWSCredentialsProvider; |
||||
|
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
||||
|
import com.amazonaws.auth.BasicAWSCredentials; |
||||
|
import com.amazonaws.client.builder.AwsClientBuilder; |
||||
|
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; |
||||
|
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; |
||||
|
import com.amazonaws.services.securitytoken.model.Credentials; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.dromara.common.oss.core.OssClient; |
||||
|
import org.dromara.common.sdk.cloudapi.storage.CredentialsToken; |
||||
|
|
||||
|
/** |
||||
|
* @auther wuyuan |
||||
|
* @data 2025/2/15 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
public class Minio { |
||||
|
|
||||
|
public static CredentialsToken getCredentials(OssClient client) { |
||||
|
try { |
||||
|
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(client.getOssProperties().getEndpoint(), client.getOssProperties().getRegion()); |
||||
|
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(client.getOssProperties().getAccessKey(), client.getOssProperties().getSecretKey()); |
||||
|
AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(basicAWSCredentials); |
||||
|
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard() |
||||
|
.withEndpointConfiguration(endpointConfiguration) |
||||
|
.withCredentials(credentialsProvider).build(); |
||||
|
Credentials credentials = stsClient.getSessionToken().getCredentials(); |
||||
|
return new CredentialsToken(credentials.getAccessKeyId(), credentials.getSecretAccessKey(), credentials.getSessionToken(), client.getOssProperties().getExpire()); |
||||
|
} catch (Exception e) { |
||||
|
log.debug("Failed to obtain sts."); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
@ -1,4 +1,4 @@ |
|||||
package com.dji.sample.component.redis; |
package org.dromara.common.redis.config; |
||||
|
|
||||
/** |
/** |
||||
* @author sean |
* @author sean |
@ -1,4 +1,4 @@ |
|||||
package com.dji.sample.component.redis; |
package org.dromara.common.redis.utils; |
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
import org.springframework.data.redis.core.RedisTemplate; |
@ -1,4 +1,4 @@ |
|||||
package com.dji.sample.component.websocket.config; |
package org.dromara.common.websocket.config; |
||||
|
|
||||
import org.springframework.web.socket.WebSocketSession; |
import org.springframework.web.socket.WebSocketSession; |
||||
import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator; |
import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator; |
@ -0,0 +1,83 @@ |
|||||
|
package org.dromara.common.websocket.dto; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
|
import io.swagger.v3.oas.annotations.media.Schema; |
||||
|
import jakarta.validation.constraints.Min; |
||||
|
import jakarta.validation.constraints.NotNull; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* The format of WebSocket messages that the pilot can receive. |
||||
|
* @author sean.zhou |
||||
|
* @date 2021/11/17 |
||||
|
* @version 0.1 |
||||
|
*/ |
||||
|
@Schema(description = "The format of WebSocket messages that the pilot can receive.") |
||||
|
public class WebSocketMessageResponse<T> { |
||||
|
|
||||
|
@JsonProperty("biz_code") |
||||
|
@NotNull |
||||
|
@Schema(description = "webSocket messages identity", implementation = BizCodeEnum.class) |
||||
|
private String bizCode; |
||||
|
|
||||
|
@Schema(description = "webSocket messages version") |
||||
|
private String version = "1.0"; |
||||
|
|
||||
|
@NotNull |
||||
|
@Min(123456789012L) |
||||
|
@Schema(description = "timestamp (milliseconds)") |
||||
|
private Long timestamp; |
||||
|
|
||||
|
@NotNull |
||||
|
@Schema(description = "Data corresponding to business functions") |
||||
|
private T data; |
||||
|
|
||||
|
public WebSocketMessageResponse() { |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "WebSocketMessageResponse{" + |
||||
|
"bizCode=" + bizCode + |
||||
|
", version='" + version + '\'' + |
||||
|
", timestamp=" + timestamp + |
||||
|
", data=" + data + |
||||
|
'}'; |
||||
|
} |
||||
|
|
||||
|
public String getBizCode() { |
||||
|
return bizCode; |
||||
|
} |
||||
|
|
||||
|
public WebSocketMessageResponse<T> setBizCode(String bizCode) { |
||||
|
this.bizCode = bizCode; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public String getVersion() { |
||||
|
return version; |
||||
|
} |
||||
|
|
||||
|
public WebSocketMessageResponse<T> setVersion(String version) { |
||||
|
this.version = version; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public Long getTimestamp() { |
||||
|
return timestamp; |
||||
|
} |
||||
|
|
||||
|
public WebSocketMessageResponse<T> setTimestamp(Long timestamp) { |
||||
|
this.timestamp = timestamp; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public T getData() { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
public WebSocketMessageResponse<T> setData(T data) { |
||||
|
this.data = data; |
||||
|
return this; |
||||
|
} |
||||
|
} |
@ -0,0 +1,138 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<parent> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>dk-modules</artifactId> |
||||
|
<version>${revision}</version> |
||||
|
</parent> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
|
||||
|
<artifactId>sample</artifactId> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-nacos</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-core</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-cloudsdk</artifactId> |
||||
|
<version>2.2.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-sentinel</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- RuoYi Common Log --> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-log</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-dict</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-doc</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-web</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-mybatis</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-dubbo</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-seata</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-idempotent</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-tenant</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-security</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-translation</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-sensitive</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-encrypt</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- RuoYi Api System --> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>api-system</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>api-resource</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-websocket</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dom4j</groupId> |
||||
|
<artifactId>dom4j</artifactId> |
||||
|
<version>2.1.3</version> |
||||
|
<scope>compile</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.dromara</groupId> |
||||
|
<artifactId>common-oss</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.amazonaws</groupId> |
||||
|
<artifactId>aws-java-sdk-s3</artifactId> |
||||
|
<version>1.12.261</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.amazonaws</groupId> |
||||
|
<artifactId>aws-java-sdk-sts</artifactId> |
||||
|
<version>1.12.261</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
</project> |
@ -1,88 +0,0 @@ |
|||||
package com.dji.sample.common.model; |
|
||||
|
|
||||
import com.auth0.jwt.interfaces.Claim; |
|
||||
import com.fasterxml.jackson.annotation.JsonAlias; |
|
||||
import lombok.AllArgsConstructor; |
|
||||
import lombok.Data; |
|
||||
import lombok.NoArgsConstructor; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
|
|
||||
import java.lang.reflect.Field; |
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
|
|
||||
/** |
|
||||
* A custom claim for storing custom information in the token. |
|
||||
* @author sean.zhou |
|
||||
* @date 2021/11/16 |
|
||||
* @version 0.1 |
|
||||
*/ |
|
||||
@AllArgsConstructor |
|
||||
@NoArgsConstructor |
|
||||
@Data |
|
||||
@Slf4j |
|
||||
public class CustomClaim { |
|
||||
|
|
||||
/** |
|
||||
* The id of the account. |
|
||||
*/ |
|
||||
private String id; |
|
||||
|
|
||||
private String username; |
|
||||
|
|
||||
@JsonAlias("user_type") |
|
||||
private Integer userType; |
|
||||
|
|
||||
@JsonAlias("workspace_id") |
|
||||
private String workspaceId; |
|
||||
|
|
||||
/** |
|
||||
* Convert the custom claim data type to the Map type. |
|
||||
* @return map |
|
||||
*/ |
|
||||
public ConcurrentHashMap<String, String> convertToMap() { |
|
||||
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(4); |
|
||||
try { |
|
||||
Field[] declaredFields = this.getClass().getDeclaredFields(); |
|
||||
for (Field field : declaredFields) { |
|
||||
JsonAlias annotation = field.getAnnotation(JsonAlias.class); |
|
||||
field.setAccessible(true); |
|
||||
// The value of key is named underscore.
|
|
||||
map.put(annotation != null ? annotation.value()[0] : field.getName(), |
|
||||
field.get(this).toString()); |
|
||||
} |
|
||||
} catch (IllegalAccessException e) { |
|
||||
log.info("CustomClaim converts failed. {}", this.toString()); |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return map; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Convert the data in Map into a custom claim object. |
|
||||
* @param claimMap |
|
||||
*/ |
|
||||
public CustomClaim (Map<String, Claim> claimMap) { |
|
||||
Field[] declaredFields = this.getClass().getDeclaredFields(); |
|
||||
for (Field field : declaredFields) { |
|
||||
field.setAccessible(true); |
|
||||
JsonAlias annotation = field.getAnnotation(JsonAlias.class); |
|
||||
|
|
||||
Claim value = claimMap.get(annotation == null ? field.getName() : annotation.value()[0]); |
|
||||
try { |
|
||||
Class<?> type = field.getType(); |
|
||||
if (Integer.class.equals(type)) { |
|
||||
field.set(this, Integer.valueOf(value.asString())); |
|
||||
continue; |
|
||||
} |
|
||||
if (String.class.equals(type)) { |
|
||||
field.set(this, value.asString()); |
|
||||
continue; |
|
||||
} |
|
||||
} catch (IllegalAccessException e) { |
|
||||
log.info("Claim parses failed. {}", claimMap.toString()); |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,144 +0,0 @@ |
|||||
package com.dji.sample.common.util; |
|
||||
|
|
||||
import com.auth0.jwt.JWT; |
|
||||
import com.auth0.jwt.JWTCreator; |
|
||||
import com.auth0.jwt.algorithms.Algorithm; |
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException; |
|
||||
import com.auth0.jwt.interfaces.DecodedJWT; |
|
||||
import com.dji.sample.common.model.CustomClaim; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
|
|
||||
import java.util.*; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Component |
|
||||
public class JwtUtil { |
|
||||
|
|
||||
private static String issuer; |
|
||||
|
|
||||
private static String subject; |
|
||||
|
|
||||
private static long age; |
|
||||
|
|
||||
private static String secret; |
|
||||
|
|
||||
public static Algorithm algorithm; |
|
||||
|
|
||||
@Value("${jwt.issuer: DJI}") |
|
||||
private void setIssuer(String issuer) { |
|
||||
JwtUtil.issuer = issuer; |
|
||||
} |
|
||||
|
|
||||
@Value("${jwt.subject: CloudApiSample}") |
|
||||
private void setSubject(String subject) { |
|
||||
JwtUtil.subject = subject; |
|
||||
} |
|
||||
|
|
||||
@Value("${jwt.age: 86400}") |
|
||||
private void setAge(long age) { |
|
||||
JwtUtil.age = age * 1000; |
|
||||
} |
|
||||
|
|
||||
@Value("${jwt.secret: CloudApiSample}") |
|
||||
private void setSecret(String secret) { |
|
||||
JwtUtil.secret = secret; |
|
||||
setAlgorithm(); |
|
||||
} |
|
||||
|
|
||||
private void setAlgorithm() { |
|
||||
JwtUtil.algorithm = Algorithm.HMAC256(secret); |
|
||||
} |
|
||||
|
|
||||
private JwtUtil() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Create a token based on custom information. |
|
||||
* @param claims custom information |
|
||||
* @return token |
|
||||
*/ |
|
||||
public static String createToken(Map<String, ?> claims) { |
|
||||
return JwtUtil.createToken(claims, age, algorithm, subject, issuer); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
* @param claims |
|
||||
* @param age unit: s |
|
||||
* @param algorithm |
|
||||
* @param subject |
|
||||
* @param issuer |
|
||||
* @return |
|
||||
*/ |
|
||||
public static String createToken(Map<String, ?> claims, Long age, Algorithm algorithm, String subject, String issuer) { |
|
||||
if (Objects.isNull(algorithm)) { |
|
||||
throw new IllegalArgumentException(); |
|
||||
} |
|
||||
|
|
||||
Date now = new Date(); |
|
||||
JWTCreator.Builder builder = JWT.create(); |
|
||||
// Add custom information to the token's payload segment.
|
|
||||
claims.forEach((k, v) -> { |
|
||||
if (Objects.nonNull(v.getClass().getClassLoader())) { |
|
||||
log.error("claim can't be set to a custom object."); |
|
||||
return; |
|
||||
} |
|
||||
if (v instanceof Map) { |
|
||||
builder.withClaim(k, (Map) v); |
|
||||
} else if (v instanceof List) { |
|
||||
builder.withClaim(k, (List) v); |
|
||||
} else { |
|
||||
builder.withClaim(k, String.valueOf(v)); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
if (StringUtils.hasText(subject)) { |
|
||||
builder.withSubject(subject); |
|
||||
} |
|
||||
|
|
||||
if (StringUtils.hasText(issuer)) { |
|
||||
builder.withIssuer(issuer); |
|
||||
} |
|
||||
|
|
||||
if (Objects.nonNull(age)) { |
|
||||
builder.withExpiresAt(new Date(now.getTime() + age)); |
|
||||
} |
|
||||
|
|
||||
String token = builder |
|
||||
.withIssuedAt(now) |
|
||||
.withNotBefore(now) |
|
||||
.sign(algorithm); |
|
||||
log.debug("token created. " + token); |
|
||||
return token; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Verify that the token is valid. |
|
||||
* @param token |
|
||||
* @return |
|
||||
* @throws TokenExpiredException |
|
||||
*/ |
|
||||
public static DecodedJWT verifyToken(String token) { |
|
||||
return JWT.require(algorithm).build().verify(token); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parses the custom information in the token into a CustomClaim object. |
|
||||
* @param token |
|
||||
* @return custom claim |
|
||||
*/ |
|
||||
public static Optional<CustomClaim> parseToken(String token) { |
|
||||
DecodedJWT jwt; |
|
||||
try { |
|
||||
jwt = verifyToken(token); |
|
||||
} catch (Exception e) { |
|
||||
e.printStackTrace(); |
|
||||
return Optional.empty(); |
|
||||
} |
|
||||
return Optional.of(new CustomClaim(jwt.getClaims())); |
|
||||
} |
|
||||
} |
|
@ -1,60 +0,0 @@ |
|||||
package com.dji.sample.component; |
|
||||
|
|
||||
import com.dji.sample.common.error.CommonErrorEnum; |
|
||||
import com.dji.sample.common.model.CustomClaim; |
|
||||
import com.dji.sample.common.util.JwtUtil; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.http.HttpMethod; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
import org.springframework.web.servlet.HandlerInterceptor; |
|
||||
import org.springframework.web.servlet.ModelAndView; |
|
||||
|
|
||||
import javax.servlet.http.HttpServletRequest; |
|
||||
import javax.servlet.http.HttpServletResponse; |
|
||||
import java.util.Optional; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Component |
|
||||
public class AuthInterceptor implements HandlerInterceptor { |
|
||||
|
|
||||
public static final String PARAM_TOKEN = "x-auth-token"; |
|
||||
|
|
||||
public static final String TOKEN_CLAIM = "customClaim"; |
|
||||
|
|
||||
@Override |
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
|
||||
String uri = request.getRequestURI(); |
|
||||
log.debug("request uri: {}, IP: {}", uri, request.getRemoteAddr()); |
|
||||
// The options method is passed directly.
|
|
||||
if (HttpMethod.OPTIONS.matches(request.getMethod())) { |
|
||||
response.setStatus(HttpStatus.OK.value()); |
|
||||
return false; |
|
||||
} |
|
||||
String token = request.getHeader(PARAM_TOKEN); |
|
||||
// Check if the token exists.
|
|
||||
if (!StringUtils.hasText(token)) { |
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value()); |
|
||||
log.error(CommonErrorEnum.NO_TOKEN.getMessage()); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// Check if the current token is valid.
|
|
||||
Optional<CustomClaim> customClaimOpt = JwtUtil.parseToken(token); |
|
||||
if (customClaimOpt.isEmpty()) { |
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value()); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// Put the custom data from the token into the request.
|
|
||||
request.setAttribute(TOKEN_CLAIM, customClaimOpt.get()); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { |
|
||||
// Delete the custom data in the request after the request ends.
|
|
||||
request.removeAttribute(TOKEN_CLAIM); |
|
||||
} |
|
||||
} |
|
@ -1,35 +0,0 @@ |
|||||
package com.dji.sample.component; |
|
||||
|
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
import javax.servlet.*; |
|
||||
import javax.servlet.http.HttpServletRequest; |
|
||||
import javax.servlet.http.HttpServletResponse; |
|
||||
import java.io.IOException; |
|
||||
|
|
||||
import static com.dji.sample.component.AuthInterceptor.PARAM_TOKEN; |
|
||||
|
|
||||
/** |
|
||||
* @author sean.zhou |
|
||||
* @version 0.1 |
|
||||
* @date 2021/11/22 |
|
||||
*/ |
|
||||
@Component |
|
||||
public class CorsFilter implements Filter { |
|
||||
|
|
||||
@Override |
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { |
|
||||
HttpServletResponse res = (HttpServletResponse) response; |
|
||||
res.addHeader("Access-Control-Allow-Credentials", "true"); |
|
||||
res.addHeader("Access-Control-Allow-Origin", "*"); |
|
||||
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); |
|
||||
res.addHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers," + |
|
||||
"Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, "+ |
|
||||
"Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive," + |
|
||||
" User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma," + PARAM_TOKEN); |
|
||||
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { |
|
||||
return; |
|
||||
} |
|
||||
filterChain.doFilter(request, response); |
|
||||
} |
|
||||
} |
|
@ -1,24 +0,0 @@ |
|||||
package com.dji.sample.component.mybatis; |
|
||||
|
|
||||
import com.baomidou.mybatisplus.annotation.DbType; |
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.context.annotation.Configuration; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.3 |
|
||||
* @date 2021/12/22 |
|
||||
*/ |
|
||||
@Configuration |
|
||||
public class MybatisPlusConfiguration { |
|
||||
|
|
||||
@Bean |
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() { |
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
|
||||
// select database
|
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); |
|
||||
return interceptor; |
|
||||
} |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
package com.dji.sample.component.mybatis; |
|
||||
|
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; |
|
||||
import org.apache.ibatis.reflection.MetaObject; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
import java.time.LocalDateTime; |
|
||||
import java.time.ZoneId; |
|
||||
|
|
||||
/** |
|
||||
* Automatic filling for set values |
|
||||
*/ |
|
||||
@Component |
|
||||
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { |
|
||||
|
|
||||
/** |
|
||||
* Automatic filling when inserting into the database. |
|
||||
* @param metaObject |
|
||||
*/ |
|
||||
@Override |
|
||||
public void insertFill(MetaObject metaObject) { |
|
||||
this.strictInsertFill(metaObject, "createTime", Long.class, |
|
||||
LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); |
|
||||
this.strictInsertFill(metaObject, "updateTime", Long.class, |
|
||||
LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Automatic filling when updating the data. |
|
||||
* @param metaObject |
|
||||
*/ |
|
||||
@Override |
|
||||
public void updateFill(MetaObject metaObject) { |
|
||||
this.strictUpdateFill(metaObject, "updateTime", Long.class, |
|
||||
LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); |
|
||||
} |
|
||||
} |
|
@ -1,93 +0,0 @@ |
|||||
package com.dji.sample.component.oss.model; |
|
||||
|
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.2 |
|
||||
* @date 2021/12/9 |
|
||||
*/ |
|
||||
@ConfigurationProperties(prefix = "oss") |
|
||||
@Component |
|
||||
public class OssConfiguration { |
|
||||
|
|
||||
/** |
|
||||
* @see OssTypeEnum |
|
||||
*/ |
|
||||
public static OssTypeEnum provider; |
|
||||
|
|
||||
/** |
|
||||
* Whether to use the object storage service. |
|
||||
*/ |
|
||||
public static boolean enable; |
|
||||
|
|
||||
/** |
|
||||
* The protocol needs to be included at the beginning of the address. |
|
||||
*/ |
|
||||
public static String endpoint; |
|
||||
|
|
||||
public static String accessKey; |
|
||||
|
|
||||
public static String secretKey; |
|
||||
|
|
||||
public static String region; |
|
||||
|
|
||||
public static Long expire; |
|
||||
|
|
||||
public static String roleSessionName; |
|
||||
|
|
||||
public static String roleArn; |
|
||||
|
|
||||
public static String bucket; |
|
||||
|
|
||||
public static String objectDirPrefix; |
|
||||
|
|
||||
public void setProvider(OssTypeEnum provider) { |
|
||||
OssConfiguration.provider = provider; |
|
||||
} |
|
||||
|
|
||||
public void setEnable(boolean enable) { |
|
||||
OssConfiguration.enable = enable; |
|
||||
} |
|
||||
|
|
||||
public void setEndpoint(String endpoint) { |
|
||||
OssConfiguration.endpoint = endpoint; |
|
||||
} |
|
||||
|
|
||||
public void setAccessKey(String accessKey) { |
|
||||
OssConfiguration.accessKey = accessKey; |
|
||||
} |
|
||||
|
|
||||
public void setSecretKey(String secretKey) { |
|
||||
OssConfiguration.secretKey = secretKey; |
|
||||
} |
|
||||
|
|
||||
public void setRegion(String region) { |
|
||||
OssConfiguration.region = region; |
|
||||
} |
|
||||
|
|
||||
public void setExpire(Long expire) { |
|
||||
OssConfiguration.expire = expire; |
|
||||
} |
|
||||
|
|
||||
public void setRoleSessionName(String roleSessionName) { |
|
||||
OssConfiguration.roleSessionName = roleSessionName; |
|
||||
} |
|
||||
|
|
||||
public void setRoleArn(String roleArn) { |
|
||||
OssConfiguration.roleArn = roleArn; |
|
||||
} |
|
||||
|
|
||||
public void setBucket(String bucket) { |
|
||||
OssConfiguration.bucket = bucket; |
|
||||
} |
|
||||
|
|
||||
public void setObjectDirPrefix(String objectDirPrefix) { |
|
||||
OssConfiguration.objectDirPrefix = objectDirPrefix; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
@ -1,51 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service; |
|
||||
|
|
||||
import com.dji.sdk.cloudapi.storage.CredentialsToken; |
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
|
|
||||
import java.io.InputStream; |
|
||||
import java.net.URL; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.3 |
|
||||
* @date 2021/12/23 |
|
||||
*/ |
|
||||
public interface IOssService { |
|
||||
|
|
||||
OssTypeEnum getOssType(); |
|
||||
|
|
||||
/** |
|
||||
* Get temporary credentials. |
|
||||
* @return |
|
||||
*/ |
|
||||
CredentialsToken getCredentials(); |
|
||||
|
|
||||
/** |
|
||||
* Get the address of the object based on the bucket name and the object name. |
|
||||
* @param bucket bucket name |
|
||||
* @param objectKey object name |
|
||||
* @return download link |
|
||||
*/ |
|
||||
URL getObjectUrl(String bucket, String objectKey); |
|
||||
|
|
||||
/** |
|
||||
* Deletes the object in the storage bucket. |
|
||||
* @param bucket |
|
||||
* @param objectKey |
|
||||
* @return |
|
||||
*/ |
|
||||
Boolean deleteObject(String bucket, String objectKey); |
|
||||
|
|
||||
/** |
|
||||
* Get the contents of an object. |
|
||||
* @param bucket |
|
||||
* @param objectKey |
|
||||
* @return |
|
||||
*/ |
|
||||
InputStream getObject(String bucket, String objectKey); |
|
||||
|
|
||||
void putObject(String bucket, String objectKey, InputStream input); |
|
||||
|
|
||||
void createClient(); |
|
||||
} |
|
@ -1,120 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service.impl; |
|
||||
|
|
||||
import com.aliyun.oss.OSS; |
|
||||
import com.aliyun.oss.OSSClientBuilder; |
|
||||
import com.aliyun.oss.OSSException; |
|
||||
import com.aliyun.oss.model.ObjectMetadata; |
|
||||
import com.aliyun.oss.model.PutObjectRequest; |
|
||||
import com.aliyun.oss.model.PutObjectResult; |
|
||||
import com.aliyuncs.DefaultAcsClient; |
|
||||
import com.aliyuncs.IAcsClient; |
|
||||
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 com.dji.sample.component.oss.model.OssConfiguration; |
|
||||
import com.dji.sample.component.oss.service.IOssService; |
|
||||
import com.dji.sdk.cloudapi.storage.CredentialsToken; |
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
import java.io.InputStream; |
|
||||
import java.net.URL; |
|
||||
import java.util.Date; |
|
||||
import java.util.Objects; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.3 |
|
||||
* @date 2021/12/23 |
|
||||
*/ |
|
||||
@Service |
|
||||
@Slf4j |
|
||||
public class AliyunOssServiceImpl implements IOssService { |
|
||||
|
|
||||
private OSS ossClient; |
|
||||
|
|
||||
@Override |
|
||||
public OssTypeEnum getOssType() { |
|
||||
return OssTypeEnum.ALIYUN; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public CredentialsToken getCredentials() { |
|
||||
|
|
||||
try { |
|
||||
|
|
||||
|
|
||||
String regionId = ""; |
|
||||
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
|
|
||||
DefaultProfile.addEndpoint(regionId, "Sts", "sts.cn-hangzhou.aliyuncs.com"); |
|
||||
// 添加endpoint。适用于Java SDK 3.12.0以下版本。
|
|
||||
// DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
|
|
||||
// 构造default profile。
|
|
||||
IClientProfile profile = DefaultProfile.getProfile(regionId, OssConfiguration.accessKey, OssConfiguration.secretKey); |
|
||||
// 构造client。
|
|
||||
DefaultAcsClient client = new DefaultAcsClient(profile); |
|
||||
AssumeRoleRequest request = new AssumeRoleRequest(); |
|
||||
// 适用于Java SDK 3.12.0及以上版本。
|
|
||||
request.setSysMethod(MethodType.POST); |
|
||||
// 适用于Java SDK 3.12.0以下版本。
|
|
||||
//request.setMethod(MethodType.POST);
|
|
||||
request.setRoleArn(OssConfiguration.roleArn); |
|
||||
request.setRoleSessionName(OssConfiguration.roleSessionName); |
|
||||
request.setDurationSeconds(OssConfiguration.expire); |
|
||||
AssumeRoleResponse response = client.getAcsResponse(request); |
|
||||
|
|
||||
return new CredentialsToken(response.getCredentials().getAccessKeyId(), response.getCredentials().getAccessKeySecret(), response.getCredentials().getSecurityToken(), OssConfiguration.expire); |
|
||||
} catch (ClientException e) { |
|
||||
log.debug("Failed to obtain sts."); |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public URL getObjectUrl(String bucket, String objectKey) { |
|
||||
// First check if the object can be fetched.
|
|
||||
boolean isExist = ossClient.doesObjectExist(bucket, objectKey); |
|
||||
if (!isExist) { |
|
||||
throw new OSSException("The object does not exist."); |
|
||||
} |
|
||||
|
|
||||
return ossClient.generatePresignedUrl(bucket, objectKey, |
|
||||
new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000)); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Boolean deleteObject(String bucket, String objectKey) { |
|
||||
if (!ossClient.doesObjectExist(bucket, objectKey)) { |
|
||||
return true; |
|
||||
} |
|
||||
ossClient.deleteObject(bucket, objectKey); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public InputStream getObject(String bucket, String objectKey) { |
|
||||
return ossClient.getObject(bucket, objectKey).getObjectContent(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void putObject(String bucket, String objectKey, InputStream input) { |
|
||||
if (ossClient.doesObjectExist(bucket, objectKey)) { |
|
||||
throw new RuntimeException("The filename already exists."); |
|
||||
} |
|
||||
PutObjectResult objectResult = ossClient.putObject(new PutObjectRequest(bucket, objectKey, input, new ObjectMetadata())); |
|
||||
log.info("Upload FlighttaskCreateFile: {}", objectResult.getETag()); |
|
||||
} |
|
||||
|
|
||||
public void createClient() { |
|
||||
if (Objects.nonNull(this.ossClient)) { |
|
||||
return; |
|
||||
} |
|
||||
this.ossClient = new OSSClientBuilder() |
|
||||
.build(OssConfiguration.endpoint, OssConfiguration.accessKey, OssConfiguration.secretKey); |
|
||||
} |
|
||||
} |
|
@ -1,126 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service.impl; |
|
||||
|
|
||||
import com.amazonaws.HttpMethod; |
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
|
||||
import com.amazonaws.auth.BasicAWSCredentials; |
|
||||
import com.amazonaws.services.s3.AmazonS3; |
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; |
|
||||
import com.amazonaws.services.s3.model.*; |
|
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; |
|
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; |
|
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; |
|
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleResult; |
|
||||
import com.amazonaws.services.securitytoken.model.Credentials; |
|
||||
import com.dji.sample.component.AuthInterceptor; |
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
|
||||
import com.dji.sample.component.oss.service.IOssService; |
|
||||
import com.dji.sdk.cloudapi.storage.CredentialsToken; |
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
import javax.annotation.PostConstruct; |
|
||||
import java.io.InputStream; |
|
||||
import java.net.URL; |
|
||||
import java.util.ArrayList; |
|
||||
import java.util.Date; |
|
||||
import java.util.List; |
|
||||
import java.util.Objects; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.0 |
|
||||
* @date 2022/4/27 |
|
||||
*/ |
|
||||
@Slf4j |
|
||||
@Service |
|
||||
public class AmazonS3ServiceImpl implements IOssService { |
|
||||
|
|
||||
private AmazonS3 client; |
|
||||
|
|
||||
@Override |
|
||||
public OssTypeEnum getOssType() { |
|
||||
return OssTypeEnum.AWS; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public CredentialsToken getCredentials() { |
|
||||
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard() |
|
||||
.withCredentials(new AWSStaticCredentialsProvider( |
|
||||
new BasicAWSCredentials(OssConfiguration.accessKey, OssConfiguration.secretKey))) |
|
||||
.withRegion(OssConfiguration.region).build(); |
|
||||
|
|
||||
AssumeRoleRequest request = new AssumeRoleRequest() |
|
||||
.withRoleArn(OssConfiguration.roleArn) |
|
||||
.withRoleSessionName(OssConfiguration.roleSessionName) |
|
||||
.withDurationSeconds(Math.toIntExact(OssConfiguration.expire)); |
|
||||
AssumeRoleResult result = stsClient.assumeRole(request); |
|
||||
Credentials credentials = result.getCredentials(); |
|
||||
return new CredentialsToken(credentials.getAccessKeyId(), credentials.getSecretAccessKey(), |
|
||||
credentials.getSessionToken(), (credentials.getExpiration().getTime() - System.currentTimeMillis()) / 1000); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public URL getObjectUrl(String bucket, String objectKey) { |
|
||||
return client.generatePresignedUrl(bucket, objectKey, |
|
||||
new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000), HttpMethod.GET); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Boolean deleteObject(String bucket, String objectKey) { |
|
||||
if (!client.doesObjectExist(bucket, objectKey)) { |
|
||||
return true; |
|
||||
} |
|
||||
client.deleteObject(bucket, objectKey); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public InputStream getObject(String bucket, String objectKey) { |
|
||||
return client.getObject(bucket, objectKey).getObjectContent().getDelegateStream(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void putObject(String bucket, String objectKey, InputStream input) { |
|
||||
if (client.doesObjectExist(bucket, objectKey)) { |
|
||||
throw new RuntimeException("The filename already exists."); |
|
||||
} |
|
||||
PutObjectResult objectResult = client.putObject(new PutObjectRequest(bucket, objectKey, input, new ObjectMetadata())); |
|
||||
log.info("Upload FlighttaskCreateFile: {}", objectResult.toString()); |
|
||||
} |
|
||||
|
|
||||
public void createClient() { |
|
||||
if (Objects.nonNull(this.client)) { |
|
||||
return; |
|
||||
} |
|
||||
this.client = AmazonS3ClientBuilder.standard() |
|
||||
.withCredentials( |
|
||||
new AWSStaticCredentialsProvider( |
|
||||
new BasicAWSCredentials(OssConfiguration.accessKey, OssConfiguration.secretKey))) |
|
||||
.withRegion(OssConfiguration.region) |
|
||||
.build(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Configuring cross-origin resource sharing |
|
||||
*/ |
|
||||
@PostConstruct |
|
||||
private void configCORS() { |
|
||||
if (!OssConfiguration.enable || !OssTypeEnum.AWS.getType().equals(OssConfiguration.provider)) { |
|
||||
return; |
|
||||
} |
|
||||
List<CORSRule.AllowedMethods> allowedMethods = new ArrayList<>(); |
|
||||
allowedMethods.add(CORSRule.AllowedMethods.GET); |
|
||||
allowedMethods.add(CORSRule.AllowedMethods.POST); |
|
||||
allowedMethods.add(CORSRule.AllowedMethods.DELETE); |
|
||||
|
|
||||
CORSRule rule = new CORSRule() |
|
||||
.withId("CORSAccessRule") |
|
||||
.withAllowedOrigins(List.of("*")) |
|
||||
.withAllowedHeaders(List.of(AuthInterceptor.PARAM_TOKEN)) |
|
||||
.withAllowedMethods(allowedMethods); |
|
||||
|
|
||||
client.setBucketCrossOriginConfiguration(OssConfiguration.bucket, |
|
||||
new BucketCrossOriginConfiguration().withRules(rule)); |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,140 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service.impl; |
|
||||
|
|
||||
import com.amazonaws.auth.AWSCredentialsProvider; |
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
|
||||
import com.amazonaws.auth.BasicAWSCredentials; |
|
||||
import com.amazonaws.auth.BasicSessionCredentials; |
|
||||
import com.amazonaws.client.builder.AwsClientBuilder; |
|
||||
import com.amazonaws.services.s3.AmazonS3; |
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; |
|
||||
import com.amazonaws.services.s3.model.S3Object; |
|
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; |
|
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; |
|
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; |
|
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleResult; |
|
||||
import com.amazonaws.services.securitytoken.model.Credentials; |
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
|
||||
import com.dji.sample.component.oss.service.IOssService; |
|
||||
import com.dji.sdk.cloudapi.storage.CredentialsToken; |
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
import io.minio.*; |
|
||||
import io.minio.credentials.AssumeRoleProvider; |
|
||||
import io.minio.errors.*; |
|
||||
import io.minio.http.Method; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
import java.io.ByteArrayInputStream; |
|
||||
import java.io.IOException; |
|
||||
import java.io.InputStream; |
|
||||
import java.net.URL; |
|
||||
import java.security.InvalidKeyException; |
|
||||
import java.security.NoSuchAlgorithmException; |
|
||||
import java.util.Objects; |
|
||||
|
|
||||
import static com.dji.sample.component.oss.model.OssConfiguration.*; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.3 |
|
||||
* @date 2021/12/23 |
|
||||
*/ |
|
||||
@Service |
|
||||
@Slf4j |
|
||||
public class MinIOServiceImpl implements IOssService { |
|
||||
|
|
||||
private MinioClient client; |
|
||||
|
|
||||
@Override |
|
||||
public OssTypeEnum getOssType() { |
|
||||
return OssTypeEnum.MINIO; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public CredentialsToken getCredentials() { |
|
||||
try { |
|
||||
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endpoint, region); |
|
||||
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey, secretKey); |
|
||||
AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(basicAWSCredentials); |
|
||||
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard() |
|
||||
.withEndpointConfiguration(endpointConfiguration) |
|
||||
.withCredentials(credentialsProvider).build(); |
|
||||
Credentials credentials = stsClient.getSessionToken().getCredentials(); |
|
||||
return new CredentialsToken(credentials.getAccessKeyId(), credentials.getSecretAccessKey(), credentials.getSessionToken(), OssConfiguration.expire); |
|
||||
} catch (Exception e) { |
|
||||
log.debug("Failed to obtain sts."); |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public URL getObjectUrl(String bucket, String objectKey) { |
|
||||
try { |
|
||||
return new URL( |
|
||||
client.getPresignedObjectUrl( |
|
||||
GetPresignedObjectUrlArgs.builder() |
|
||||
.method(Method.GET) |
|
||||
.bucket(bucket) |
|
||||
.object(objectKey) |
|
||||
.expiry(Math.toIntExact(OssConfiguration.expire)) |
|
||||
.build())); |
|
||||
} catch (ErrorResponseException | InsufficientDataException | InternalException | |
|
||||
InvalidKeyException | InvalidResponseException | IOException | |
|
||||
NoSuchAlgorithmException | XmlParserException | ServerException e) { |
|
||||
throw new RuntimeException("The file does not exist on the OssConfiguration."); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Boolean deleteObject(String bucket, String objectKey) { |
|
||||
try { |
|
||||
client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build()); |
|
||||
} catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) { |
|
||||
log.error("Failed to delete file."); |
|
||||
e.printStackTrace(); |
|
||||
return false; |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public InputStream getObject(String bucket, String objectKey) { |
|
||||
try { |
|
||||
GetObjectResponse object = client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build()); |
|
||||
return new ByteArrayInputStream(object.readAllBytes()); |
|
||||
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return InputStream.nullInputStream(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void putObject(String bucket, String objectKey, InputStream input) { |
|
||||
try { |
|
||||
client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectKey).build()); |
|
||||
throw new RuntimeException("The filename already exists."); |
|
||||
} catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { |
|
||||
log.info("The file does not exist, start uploading."); |
|
||||
try { |
|
||||
ObjectWriteResponse response = client.putObject( |
|
||||
PutObjectArgs.builder().bucket(bucket).object(objectKey).stream(input, input.available(), 0).build()); |
|
||||
log.info("Upload FlighttaskCreateFile: {}", response.etag()); |
|
||||
} catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException ex) { |
|
||||
log.error("Failed to upload FlighttaskCreateFile {}.", objectKey); |
|
||||
ex.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void createClient() { |
|
||||
if (Objects.nonNull(this.client)) { |
|
||||
return; |
|
||||
} |
|
||||
this.client = MinioClient.builder() |
|
||||
.endpoint(OssConfiguration.endpoint) |
|
||||
.credentials(accessKey, secretKey) |
|
||||
.region(region) |
|
||||
.build(); |
|
||||
} |
|
||||
} |
|
@ -1,31 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service.impl; |
|
||||
|
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
|
||||
import org.aspectj.lang.annotation.Aspect; |
|
||||
import org.aspectj.lang.annotation.Before; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.1 |
|
||||
* @date 2022/6/20 |
|
||||
*/ |
|
||||
@Component |
|
||||
@Aspect |
|
||||
public class OssAspectHandler { |
|
||||
|
|
||||
@Autowired |
|
||||
private OssServiceContext ossServiceContext; |
|
||||
|
|
||||
@Before("execution(public * com.dji.sample.component.oss.service.impl.OssServiceContext.*(..))") |
|
||||
public void before() { |
|
||||
if (!OssConfiguration.enable) { |
|
||||
throw new IllegalArgumentException("请启用OSS配置。"); |
|
||||
} |
|
||||
if (this.ossServiceContext.getOssService() == null) { |
|
||||
throw new IllegalArgumentException("请检查OSS配置配置。"); |
|
||||
} |
|
||||
this.ossServiceContext.createClient(); |
|
||||
} |
|
||||
} |
|
@ -1,68 +0,0 @@ |
|||||
package com.dji.sample.component.oss.service.impl; |
|
||||
|
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
|
||||
import com.dji.sample.component.oss.service.IOssService; |
|
||||
import com.dji.sdk.cloudapi.storage.CredentialsToken; |
|
||||
import com.dji.sdk.cloudapi.storage.OssTypeEnum; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
|
|
||||
import java.io.InputStream; |
|
||||
import java.net.URL; |
|
||||
import java.util.Arrays; |
|
||||
import java.util.List; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.0 |
|
||||
* @date 2022/5/30 |
|
||||
*/ |
|
||||
@Service |
|
||||
public class OssServiceContext { |
|
||||
|
|
||||
private IOssService ossService; |
|
||||
|
|
||||
@Autowired |
|
||||
public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) { |
|
||||
if (!OssConfiguration.enable) { |
|
||||
return; |
|
||||
} |
|
||||
this.ossService = ossServices.stream() |
|
||||
.filter(ossService -> ossService.getOssType() == OssConfiguration.provider) |
|
||||
.findFirst() |
|
||||
.orElseThrow(() -> new IllegalArgumentException("Oss提供程序非法。可选: " + |
|
||||
Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray()))); |
|
||||
} |
|
||||
|
|
||||
IOssService getOssService() { |
|
||||
return this.ossService; |
|
||||
} |
|
||||
|
|
||||
public CredentialsToken getCredentials() { |
|
||||
return this.ossService.getCredentials(); |
|
||||
} |
|
||||
|
|
||||
public URL getObjectUrl(String bucket, String objectKey) { |
|
||||
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) { |
|
||||
throw new IllegalArgumentException(); |
|
||||
} |
|
||||
return this.ossService.getObjectUrl(bucket, objectKey); |
|
||||
} |
|
||||
|
|
||||
public Boolean deleteObject(String bucket, String objectKey) { |
|
||||
return this.ossService.deleteObject(bucket, objectKey); |
|
||||
} |
|
||||
|
|
||||
public InputStream getObject(String bucket, String objectKey) { |
|
||||
return this.ossService.getObject(bucket, objectKey); |
|
||||
} |
|
||||
|
|
||||
public void putObject(String bucket, String objectKey, InputStream stream) { |
|
||||
this.ossService.putObject(bucket, objectKey, stream); |
|
||||
} |
|
||||
|
|
||||
void createClient() { |
|
||||
this.ossService.createClient(); |
|
||||
} |
|
||||
} |
|
@ -1,63 +0,0 @@ |
|||||
package com.dji.sample.component.redis; |
|
||||
|
|
||||
import com.fasterxml.jackson.annotation.JsonInclude; |
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
|
||||
import com.fasterxml.jackson.databind.MapperFeature; |
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy; |
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; |
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.context.annotation.Configuration; |
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|
||||
import org.springframework.data.redis.core.RedisTemplate; |
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; |
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; |
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer; |
|
||||
|
|
||||
import java.time.LocalDateTime; |
|
||||
import java.time.format.DateTimeFormatter; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.0 |
|
||||
* @date 2022/4/19 |
|
||||
*/ |
|
||||
@Configuration |
|
||||
@EnableRedisRepositories |
|
||||
public class RedisConfiguration { |
|
||||
|
|
||||
@Bean |
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { |
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); |
|
||||
redisTemplate.setConnectionFactory(factory); |
|
||||
|
|
||||
ObjectMapper objectMapper = new ObjectMapper(); |
|
||||
JavaTimeModule timeModule = new JavaTimeModule(); |
|
||||
timeModule.addDeserializer(LocalDateTime.class, |
|
||||
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
|
||||
timeModule.addSerializer(LocalDateTime.class, |
|
||||
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
|
||||
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS); |
|
||||
objectMapper.registerModules(timeModule); |
|
||||
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), |
|
||||
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); |
|
||||
|
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); |
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); |
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
|
||||
|
|
||||
|
|
||||
StringRedisSerializer serializer = new StringRedisSerializer(); |
|
||||
redisTemplate.setKeySerializer(serializer); |
|
||||
redisTemplate.setHashKeySerializer(serializer); |
|
||||
|
|
||||
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper); |
|
||||
redisTemplate.setValueSerializer(jsonRedisSerializer); |
|
||||
redisTemplate.setHashValueSerializer(jsonRedisSerializer); |
|
||||
redisTemplate.afterPropertiesSet(); |
|
||||
return redisTemplate; |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,70 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.config; |
|
||||
|
|
||||
import com.dji.sample.common.model.CustomClaim; |
|
||||
import com.dji.sample.common.util.JwtUtil; |
|
||||
import com.dji.sample.component.AuthInterceptor; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.http.server.ServerHttpRequest; |
|
||||
import org.springframework.http.server.ServletServerHttpRequest; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
import org.springframework.web.socket.WebSocketHandler; |
|
||||
import org.springframework.web.socket.server.support.DefaultHandshakeHandler; |
|
||||
|
|
||||
import javax.servlet.http.HttpServletRequest; |
|
||||
import java.security.Principal; |
|
||||
import java.util.Map; |
|
||||
import java.util.Optional; |
|
||||
|
|
||||
/** |
|
||||
* @author sean.zhou |
|
||||
* @date 2021/11/16 |
|
||||
* @version 0.1 |
|
||||
*/ |
|
||||
@Slf4j |
|
||||
@Component |
|
||||
public class AuthPrincipalHandler extends DefaultHandshakeHandler { |
|
||||
|
|
||||
@Override |
|
||||
protected boolean isValidOrigin(ServerHttpRequest request) { |
|
||||
|
|
||||
if (request instanceof ServletServerHttpRequest) { |
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); |
|
||||
String token = servletRequest.getParameter(AuthInterceptor.PARAM_TOKEN); |
|
||||
|
|
||||
if (!StringUtils.hasText(token)) { |
|
||||
return false; |
|
||||
} |
|
||||
log.debug("token:" + token); |
|
||||
Optional<CustomClaim> customClaim = JwtUtil.parseToken(token); |
|
||||
if (customClaim.isEmpty()) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
servletRequest.setAttribute(AuthInterceptor.TOKEN_CLAIM, customClaim.get()); |
|
||||
return true; |
|
||||
} |
|
||||
return false; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* The principal's name: {workspaceId}/{userType}/{userId} |
|
||||
* @param request |
|
||||
* @param wsHandler |
|
||||
* @param attributes |
|
||||
* @return |
|
||||
*/ |
|
||||
@Override |
|
||||
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) { |
|
||||
if (request instanceof ServletServerHttpRequest) { |
|
||||
|
|
||||
// get the custom claim
|
|
||||
CustomClaim claim = (CustomClaim) ((ServletServerHttpRequest) request).getServletRequest() |
|
||||
.getAttribute(AuthInterceptor.TOKEN_CLAIM); |
|
||||
|
|
||||
return () -> claim.getWorkspaceId() + "/" + claim.getUserType() + "/" + claim.getId(); |
|
||||
} |
|
||||
return () -> null; |
|
||||
} |
|
||||
} |
|
@ -1,27 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.config; |
|
||||
|
|
||||
import com.dji.sample.component.websocket.service.IWebSocketManageService; |
|
||||
import com.dji.sdk.websocket.WebSocketDefaultFactory; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.context.annotation.Primary; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.springframework.web.socket.WebSocketHandler; |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
* @author sean.zhou |
|
||||
* @date 2021/11/16 |
|
||||
* @version 0.1 |
|
||||
*/ |
|
||||
@Component |
|
||||
@Primary |
|
||||
public class MyWebSocketFactory extends WebSocketDefaultFactory { |
|
||||
|
|
||||
@Autowired |
|
||||
private IWebSocketManageService webSocketManageService; |
|
||||
|
|
||||
@Override |
|
||||
public WebSocketHandler decorate(WebSocketHandler handler) { |
|
||||
return new MyWebSocketHandler(handler, webSocketManageService); |
|
||||
} |
|
||||
} |
|
@ -1,58 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.config; |
|
||||
|
|
||||
import com.dji.sample.component.websocket.service.IWebSocketManageService; |
|
||||
import com.dji.sdk.websocket.WebSocketDefaultHandler; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
import org.springframework.web.socket.CloseStatus; |
|
||||
import org.springframework.web.socket.WebSocketHandler; |
|
||||
import org.springframework.web.socket.WebSocketMessage; |
|
||||
import org.springframework.web.socket.WebSocketSession; |
|
||||
|
|
||||
import java.security.Principal; |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
* @author sean.zhou |
|
||||
* @date 2021/11/16 |
|
||||
* @version 0.1 |
|
||||
*/ |
|
||||
@Slf4j |
|
||||
public class MyWebSocketHandler extends WebSocketDefaultHandler { |
|
||||
|
|
||||
private IWebSocketManageService webSocketManageService; |
|
||||
|
|
||||
MyWebSocketHandler(WebSocketHandler delegate, IWebSocketManageService webSocketManageService) { |
|
||||
super(delegate); |
|
||||
this.webSocketManageService = webSocketManageService; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception { |
|
||||
Principal principal = session.getPrincipal(); |
|
||||
if (StringUtils.hasText(principal.getName())) { |
|
||||
webSocketManageService.put(principal.getName(), new MyConcurrentWebSocketSession(session)); |
|
||||
log.debug("{} is connected. ID: {}. WebSocketSession[current count: {}]", |
|
||||
principal.getName(), session.getId(), webSocketManageService.getConnectedCount()); |
|
||||
return; |
|
||||
} |
|
||||
session.close(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { |
|
||||
Principal principal = session.getPrincipal(); |
|
||||
if (StringUtils.hasText(principal.getName())) { |
|
||||
webSocketManageService.remove(principal.getName(), session.getId()); |
|
||||
log.debug("{} is disconnected. ID: {}. WebSocketSession[current count: {}]", |
|
||||
principal.getName(), session.getId(), webSocketManageService.getConnectedCount()); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { |
|
||||
log.debug("received message: {}", message.getPayload()); |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,93 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.model; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 0.1 |
|
||||
* @date 2021/11/26 |
|
||||
*/ |
|
||||
public enum BizCodeEnum { |
|
||||
|
|
||||
DEVICE_ONLINE("device_online"), |
|
||||
|
|
||||
DEVICE_OFFLINE("device_offline"), |
|
||||
|
|
||||
DEVICE_UPDATE_TOPO("device_update_topo"), |
|
||||
|
|
||||
DEVICE_OSD("device_osd"), |
|
||||
|
|
||||
RC_OSD("gateway_osd"), |
|
||||
|
|
||||
DOCK_OSD("dock_osd"), |
|
||||
|
|
||||
MAP_ELEMENT_CREATE("map_element_create"), |
|
||||
|
|
||||
MAP_ELEMENT_UPDATE("map_element_update"), |
|
||||
|
|
||||
MAP_ELEMENT_DELETE("map_element_delete"), |
|
||||
|
|
||||
MAP_GROUP_REFRESH("map_group_refresh"), |
|
||||
|
|
||||
FLIGHT_TASK_PROGRESS("flighttask_progress"), |
|
||||
|
|
||||
DEVICE_HMS("device_hms"), |
|
||||
|
|
||||
DEVICE_REBOOT("device_reboot"), |
|
||||
|
|
||||
DRONE_OPEN("drone_open"), |
|
||||
|
|
||||
DRONE_CLOSE("drone_close"), |
|
||||
|
|
||||
DEVICE_CHECK("device_check"), |
|
||||
|
|
||||
DRONE_FORMAT("drone_format"), |
|
||||
|
|
||||
DEVICE_FORMAT("device_format"), |
|
||||
|
|
||||
COVER_OPEN("cover_open"), |
|
||||
|
|
||||
COVER_CLOSE("cover_close"), |
|
||||
|
|
||||
PUTTER_OPEN("putter_open"), |
|
||||
|
|
||||
PUTTER_CLOSE("putter_close"), |
|
||||
|
|
||||
CHARGE_OPEN("charge_open"), |
|
||||
|
|
||||
CHARGE_CLOSE("charge_close"), |
|
||||
|
|
||||
FILE_UPLOAD_CALLBACK("file_upload_callback"), |
|
||||
|
|
||||
FILE_UPLOAD_PROGRESS("fileupload_progress"), |
|
||||
|
|
||||
OTA_PROGRESS("ota_progress"), |
|
||||
|
|
||||
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("highest_priority_upload_flighttask_media"), |
|
||||
|
|
||||
CONTROL_SOURCE_CHANGE("control_source_change"), |
|
||||
|
|
||||
FLY_TO_POINT_PROGRESS("fly_to_point_progress"), |
|
||||
|
|
||||
TAKE_OFF_TO_POINT_PROGRESS("takeoff_to_point_progress"), |
|
||||
|
|
||||
DRC_STATUS_NOTIFY("drc_status_notify"), |
|
||||
|
|
||||
JOYSTICK_INVALID_NOTIFY("joystick_invalid_notify"), |
|
||||
|
|
||||
FLIGHT_AREAS_SYNC_PROGRESS("flight_areas_sync_progress"), |
|
||||
|
|
||||
FLIGHT_AREAS_DRONE_LOCATION("flight_areas_drone_location"), |
|
||||
|
|
||||
FLIGHT_AREAS_UPDATE("flight_areas_update"), |
|
||||
|
|
||||
; |
|
||||
|
|
||||
private String code; |
|
||||
|
|
||||
BizCodeEnum(String code) { |
|
||||
this.code = code; |
|
||||
} |
|
||||
|
|
||||
public String getCode() { |
|
||||
return code; |
|
||||
} |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.service; |
|
||||
|
|
||||
import com.dji.sample.component.websocket.config.MyConcurrentWebSocketSession; |
|
||||
|
|
||||
import java.util.Collection; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.0 |
|
||||
* @date 2022/4/25 |
|
||||
*/ |
|
||||
public interface IWebSocketManageService { |
|
||||
|
|
||||
void put(String key, MyConcurrentWebSocketSession val); |
|
||||
|
|
||||
void remove(String key, String sessionId); |
|
||||
|
|
||||
Collection<MyConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId); |
|
||||
|
|
||||
Collection<MyConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType); |
|
||||
|
|
||||
Long getConnectedCount(); |
|
||||
} |
|
@ -1,32 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.service; |
|
||||
|
|
||||
import com.dji.sample.component.websocket.config.MyConcurrentWebSocketSession; |
|
||||
import com.dji.sdk.websocket.WebSocketMessageResponse; |
|
||||
|
|
||||
import java.util.Collection; |
|
||||
|
|
||||
/** |
|
||||
* @author sean.zhou |
|
||||
* @date 2021/11/24 |
|
||||
* @version 0.1 |
|
||||
*/ |
|
||||
public interface IWebSocketMessageService { |
|
||||
|
|
||||
/** |
|
||||
* Send a message to the specific connection. |
|
||||
* @param session A WebSocket connection object |
|
||||
* @param message message |
|
||||
*/ |
|
||||
void sendMessage(MyConcurrentWebSocketSession session, WebSocketMessageResponse message); |
|
||||
|
|
||||
/** |
|
||||
* Send the same message to specific connection. |
|
||||
* @param sessions A collection of WebSocket connection objects. |
|
||||
* @param message message |
|
||||
*/ |
|
||||
void sendBatch(Collection<MyConcurrentWebSocketSession> sessions, WebSocketMessageResponse message); |
|
||||
|
|
||||
void sendBatch(String workspaceId, Integer userType, String bizCode, Object data); |
|
||||
|
|
||||
void sendBatch(String workspaceId, String bizCode, Object data); |
|
||||
} |
|
@ -1,86 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.service.impl; |
|
||||
|
|
||||
import com.dji.sample.component.redis.RedisConst; |
|
||||
import com.dji.sample.component.redis.RedisOpsUtils; |
|
||||
import com.dji.sample.component.websocket.config.MyConcurrentWebSocketSession; |
|
||||
import com.dji.sample.component.websocket.service.IWebSocketManageService; |
|
||||
import com.dji.sample.manage.model.enums.UserTypeEnum; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
|
|
||||
import java.util.Collection; |
|
||||
import java.util.Collections; |
|
||||
import java.util.Objects; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
import java.util.stream.Collectors; |
|
||||
|
|
||||
/** |
|
||||
* @author sean |
|
||||
* @version 1.0 |
|
||||
* @date 2022/4/25 |
|
||||
*/ |
|
||||
@Slf4j |
|
||||
@Service |
|
||||
public class WebSocketManageServiceImpl implements IWebSocketManageService { |
|
||||
|
|
||||
private static final ConcurrentHashMap<String, MyConcurrentWebSocketSession> SESSIONS = new ConcurrentHashMap<>(16); |
|
||||
|
|
||||
@Override |
|
||||
public void put(String key, MyConcurrentWebSocketSession val) { |
|
||||
String[] name = key.split("/"); |
|
||||
if (name.length != 3) { |
|
||||
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]"); |
|
||||
return; |
|
||||
} |
|
||||
String sessionId = val.getId(); |
|
||||
String workspaceKey = RedisConst.WEBSOCKET_PREFIX + name[0]; |
|
||||
String userTypeKey = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(); |
|
||||
RedisOpsUtils.hashSet(workspaceKey, sessionId, name[2]); |
|
||||
RedisOpsUtils.hashSet(userTypeKey, sessionId, name[2]); |
|
||||
SESSIONS.put(sessionId, val); |
|
||||
RedisOpsUtils.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND); |
|
||||
RedisOpsUtils.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void remove(String key, String sessionId) { |
|
||||
String[] name = key.split("/"); |
|
||||
if (name.length != 3) { |
|
||||
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]"); |
|
||||
return; |
|
||||
} |
|
||||
RedisOpsUtils.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId}); |
|
||||
RedisOpsUtils.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(), new String[] {sessionId}); |
|
||||
SESSIONS.remove(sessionId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Collection<MyConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId) { |
|
||||
if (!StringUtils.hasText(workspaceId)) { |
|
||||
return Collections.emptySet(); |
|
||||
} |
|
||||
String key = RedisConst.WEBSOCKET_PREFIX + workspaceId; |
|
||||
|
|
||||
return RedisOpsUtils.hashKeys(key) |
|
||||
.stream() |
|
||||
.map(SESSIONS::get) |
|
||||
.filter(Objects::nonNull) |
|
||||
.collect(Collectors.toSet()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Collection<MyConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType) { |
|
||||
String key = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(userType).getDesc(); |
|
||||
return RedisOpsUtils.hashKeys(key) |
|
||||
.stream() |
|
||||
.map(SESSIONS::get) |
|
||||
.filter(getValueWithWorkspace(workspaceId)::contains) |
|
||||
.collect(Collectors.toSet()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Long getConnectedCount() { |
|
||||
return SESSIONS.mappingCount(); |
|
||||
} |
|
||||
} |
|
@ -1,99 +0,0 @@ |
|||||
package com.dji.sample.component.websocket.service.impl; |
|
||||
|
|
||||
import com.dji.sample.component.websocket.config.MyConcurrentWebSocketSession; |
|
||||
import com.dji.sample.component.websocket.service.IWebSocketManageService; |
|
||||
import com.dji.sample.component.websocket.service.IWebSocketMessageService; |
|
||||
import com.dji.sdk.websocket.WebSocketMessageResponse; |
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.springframework.util.StringUtils; |
|
||||
import org.springframework.web.socket.TextMessage; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Collection; |
|
||||
import java.util.Objects; |
|
||||
|
|
||||
/** |
|
||||
* @author sean.zhou |
|
||||
* @version 0.1 |
|
||||
* @date 2021/11/24 |
|
||||
*/ |
|
||||
@Service |
|
||||
@Slf4j |
|
||||
public class WebSocketMessageServiceImpl implements IWebSocketMessageService { |
|
||||
|
|
||||
@Autowired |
|
||||
private ObjectMapper mapper; |
|
||||
|
|
||||
@Autowired |
|
||||
private IWebSocketManageService webSocketManageService; |
|
||||
|
|
||||
@Override |
|
||||
public void sendMessage(MyConcurrentWebSocketSession session, WebSocketMessageResponse message) { |
|
||||
if (session == null) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
if (!session.isOpen()) { |
|
||||
session.close(); |
|
||||
log.debug("This session is closed."); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
session.sendMessage(new TextMessage(mapper.writeValueAsBytes(message))); |
|
||||
} catch (IOException e) { |
|
||||
log.info("Failed to publish the message. {}", message.toString()); |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void sendBatch(Collection<MyConcurrentWebSocketSession> sessions, WebSocketMessageResponse message) { |
|
||||
if (sessions.isEmpty()) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
|
|
||||
TextMessage data = new TextMessage(mapper.writeValueAsBytes(message)); |
|
||||
|
|
||||
for (MyConcurrentWebSocketSession session : sessions) { |
|
||||
if (!session.isOpen()) { |
|
||||
session.close(); |
|
||||
log.debug("This session is closed."); |
|
||||
return; |
|
||||
} |
|
||||
session.sendMessage(data); |
|
||||
} |
|
||||
|
|
||||
} catch (IOException e) { |
|
||||
log.info("Failed to publish the message. {}", message.toString()); |
|
||||
|
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void sendBatch(String workspaceId, Integer userType, String bizCode, Object data) { |
|
||||
if (!StringUtils.hasText(workspaceId)) { |
|
||||
throw new RuntimeException("工作区ID不存在。"); |
|
||||
} |
|
||||
Collection<MyConcurrentWebSocketSession> sessions = Objects.isNull(userType) ? |
|
||||
webSocketManageService.getValueWithWorkspace(workspaceId) : |
|
||||
webSocketManageService.getValueWithWorkspaceAndUserType(workspaceId, userType); |
|
||||
|
|
||||
this.sendBatch(sessions, new WebSocketMessageResponse() |
|
||||
.setData(Objects.requireNonNullElse(data, "")) |
|
||||
.setTimestamp(System.currentTimeMillis()) |
|
||||
.setBizCode(bizCode)); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void sendBatch(String workspaceId, String bizCode, Object data) { |
|
||||
this.sendBatch(workspaceId, null, bizCode, data); |
|
||||
} |
|
||||
} |
|
@ -1,40 +0,0 @@ |
|||||
package com.dji.sample.configuration.mvc; |
|
||||
|
|
||||
import com.dji.sample.component.AuthInterceptor; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.context.annotation.Configuration; |
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
|
||||
|
|
||||
import java.util.ArrayList; |
|
||||
import java.util.List; |
|
||||
|
|
||||
@Configuration |
|
||||
public class GlobalMVCConfigurer implements WebMvcConfigurer { |
|
||||
|
|
||||
@Autowired |
|
||||
private AuthInterceptor authInterceptor; |
|
||||
|
|
||||
private static List<String> excludePaths = new ArrayList<>(); |
|
||||
|
|
||||
@Value("${url.manage.prefix}") |
|
||||
private String managePrefix; |
|
||||
|
|
||||
@Value("${url.manage.version}") |
|
||||
private String manageVersion; |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public void addInterceptors(InterceptorRegistry registry) { |
|
||||
// Exclude the login interface.
|
|
||||
excludePaths.add("/" + managePrefix + manageVersion + "/login"); |
|
||||
excludePaths.add("/" + managePrefix + manageVersion + "/token/refresh"); |
|
||||
excludePaths.add("/swagger-ui.html"); |
|
||||
excludePaths.add("/swagger-ui/**"); |
|
||||
excludePaths.add("/v3/**"); |
|
||||
excludePaths.add("/ui/**"); |
|
||||
// Intercept for all request interfaces.
|
|
||||
registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns(excludePaths); |
|
||||
} |
|
||||
} |
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue