diff options
author | crupest <crupest@outlook.com> | 2019-04-23 00:14:35 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-04-23 00:14:35 +0800 |
commit | 797b1da15c76f6598dcc48f675c1b82cb27a17ed (patch) | |
tree | 99754727d79f8ae27c96f35e2541d51be780deb4 /Timeline | |
parent | 752850049301290b991f748816c66352f578c057 (diff) | |
download | timeline-797b1da15c76f6598dcc48f675c1b82cb27a17ed.tar.gz timeline-797b1da15c76f6598dcc48f675c1b82cb27a17ed.tar.bz2 timeline-797b1da15c76f6598dcc48f675c1b82cb27a17ed.zip |
Remove qcloud cs sdk. I will write one by myself.
Develop signature algorithm.
Diffstat (limited to 'Timeline')
-rw-r--r-- | Timeline/Configs/QCloudCosConfig.cs (renamed from Timeline/Configs/TencentCosConfig.cs) | 7 | ||||
-rw-r--r-- | Timeline/Services/TencentCloudCosService.cs | 174 | ||||
-rw-r--r-- | Timeline/Services/UserService.cs | 6 | ||||
-rw-r--r-- | Timeline/Startup.cs | 4 | ||||
-rw-r--r-- | Timeline/Timeline.csproj | 1 |
5 files changed, 116 insertions, 76 deletions
diff --git a/Timeline/Configs/TencentCosConfig.cs b/Timeline/Configs/QCloudCosConfig.cs index c41669f1..6d10436c 100644 --- a/Timeline/Configs/TencentCosConfig.cs +++ b/Timeline/Configs/QCloudCosConfig.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -namespace Timeline.Configs +namespace Timeline.Configs { - public class TencentCosConfig + public class QCloudCosConfig { public string AppId { get; set; } public string Region { get; set; } diff --git a/Timeline/Services/TencentCloudCosService.cs b/Timeline/Services/TencentCloudCosService.cs index 9ab9d54d..1bfcf745 100644 --- a/Timeline/Services/TencentCloudCosService.cs +++ b/Timeline/Services/TencentCloudCosService.cs @@ -1,99 +1,143 @@ -using COSXML; -using COSXML.Auth; -using COSXML.CosException; -using COSXML.Model; -using COSXML.Model.Object; -using COSXML.Model.Tag; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; using System.Threading.Tasks; using Timeline.Configs; namespace Timeline.Services { - public interface ITencentCloudCosService + public interface IQCloudCosService { - Task<bool> Exists(string bucket, string key); + Task<bool> ObjectExists(string bucket, string key); string GetObjectUrl(string bucket, string key); } - public class TencentCloudCosService : ITencentCloudCosService + public class QCloudCosService : IQCloudCosService { - private readonly TencentCosConfig _config; - private readonly CosXmlServer _server; - private readonly ILogger<TencentCloudCosService> _logger; + private readonly QCloudCosConfig _config; + private readonly ILogger<QCloudCosService> _logger; - public TencentCloudCosService(IOptions<TencentCosConfig> config, ILogger<TencentCloudCosService> logger) + public QCloudCosService(IOptions<QCloudCosConfig> config, ILogger<QCloudCosService> logger) { _config = config.Value; _logger = logger; + } - var cosConfig = new CosXmlConfig.Builder() - .IsHttps(true) - .SetAppid(config.Value.AppId) - .SetRegion(config.Value.Region) - .SetDebugLog(true) - .Build(); + public class QCloudCredentials + { + public string SecretId { get; set; } + public string SecretKey { get; set; } + } - var credentialProvider = new DefaultQCloudCredentialProvider(config.Value.SecretId, config.Value.SecretKey, 3600); + public class RequestInfo + { + public string Method { get; set; } + public string Uri { get; set; } + public IEnumerable<KeyValuePair<string, string>> Parameters { get; set; } + public IEnumerable<KeyValuePair<string, string>> Headers { get; set; } + } - _server = new CosXmlServer(cosConfig, credentialProvider); + public class TimeDuration + { + public DateTimeOffset Start { get; set; } + public DateTimeOffset End { get; set; } } - public Task<bool> Exists(string bucket, string key) + public static string GenerateSign(QCloudCredentials credentials, RequestInfo request, TimeDuration signValidTime) { - bucket = bucket + "-" + _config.AppId; + Debug.Assert(credentials != null); + Debug.Assert(credentials.SecretId != null); + Debug.Assert(credentials.SecretKey != null); + Debug.Assert(request != null); + Debug.Assert(request.Method != null); + Debug.Assert(request.Uri != null); + Debug.Assert(request.Parameters != null); + Debug.Assert(request.Headers != null); + Debug.Assert(signValidTime != null); + Debug.Assert(signValidTime.Start < signValidTime.End, "Start must be before End in sign valid time."); + + List<(string key, string value)> Transform(IEnumerable<KeyValuePair<string, string>> raw) + { + var sorted= raw.Select(p => (key: p.Key.ToLower(), value: WebUtility.UrlEncode(p.Value))).ToList(); + sorted.Sort((left, right) => string.CompareOrdinal(left.key, right.key)); + return sorted; + } + + var transformedParameters = Transform(request.Parameters); + var transformedHeaders = Transform(request.Headers); + + List<(string, string)> result = new List<(string, string)>(); + + const string signAlgorithm = "sha1"; + result.Add(("q-sign-algorithm", signAlgorithm)); + + result.Add(("q-ak", credentials.SecretId)); + + var signTime = $"{signValidTime.Start.ToUnixTimeSeconds().ToString()};{signValidTime.End.ToUnixTimeSeconds().ToString()}"; + var keyTime = signTime; + result.Add(("q-sign-time", signTime)); + result.Add(("q-key-time", keyTime)); - var request = new HeadObjectRequest(bucket, key); + result.Add(("q-header-list", string.Join(';', transformedHeaders.Select(h => h.key)))); + result.Add(("q-url-param-list", string.Join(';', transformedParameters.Select(p => p.key)))); - var t = new TaskCompletionSource<bool>(); + HMACSHA1 hmac = new HMACSHA1(); - _server.HeadObject(request, delegate (CosResult result) + string ByteArrayToString(byte[] bytes) { - if (result.httpCode >= 200 && result.httpCode < 300) - t.TrySetResult(true); - else - t.TrySetResult(false); - }, - delegate (CosClientException clientException, CosServerException serverException) + return BitConverter.ToString(bytes).Replace("-", "").ToLower(); + } + + hmac.Key = Encoding.UTF8.GetBytes(credentials.SecretKey); + var signKey = ByteArrayToString(hmac.ComputeHash(Encoding.UTF8.GetBytes(keyTime))); + + string Join(IEnumerable<(string key, string value)> raw) { - if (clientException != null) - { - _logger.LogError(clientException, "An client error occured when test cos object existence. Bucket : {} . Key : {} .", bucket, key); - t.TrySetException(clientException); - return; - } - if (serverException != null) - { - if (serverException.statusCode == 404) - { - t.TrySetResult(false); - return; - } - _logger.LogError(serverException, "An server error occured when test cos object existence. Bucket : {} . Key : {} .", bucket, key); - t.TrySetException(serverException); - return; - } - _logger.LogError("An unknown error occured when test cos object existence. Bucket : {} . Key : {} .", bucket, key); - t.TrySetException(new Exception("Unknown exception when test cos object existence.")); - }); - - return t.Task; + return string.Join('&', raw.Select(p => string.Concat(p.key, "=", p.value))); + } + + var httpString = new StringBuilder() + .Append(request.Method).Append('\n') + .Append(request.Uri).Append('\n') + .Append(Join(transformedParameters)).Append('\n') + .Append(Join(transformedHeaders)).Append('\n') + .ToString(); + + string Sha1(string data) + { + var sha1 = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(data)); + return ByteArrayToString(sha1); + } + + var stringToSign = new StringBuilder() + .Append(signAlgorithm).Append('\n') + .Append(signTime).Append('\n') + .Append(Sha1(httpString)).Append('\n') + .ToString(); + + hmac.Key = Encoding.UTF8.GetBytes(signKey); + var signature = ByteArrayToString(hmac.ComputeHash( + Encoding.UTF8.GetBytes(stringToSign))); + + result.Add(("q-signature", signature)); + + return Join(result); + } + + public Task<bool> ObjectExists(string bucket, string key) + { + throw new NotImplementedException(); } public string GetObjectUrl(string bucket, string key) { - return _server.GenerateSignURL(new PreSignatureStruct() - { - appid = _config.AppId, - region = _config.Region, - bucket = bucket + "-" + _config.AppId, - key = key, - httpMethod = "GET", - isHttps = true, - signDurationSecond = 300 - }); + throw new NotImplementedException(); } } } diff --git a/Timeline/Services/UserService.cs b/Timeline/Services/UserService.cs index a444d434..d1555660 100644 --- a/Timeline/Services/UserService.cs +++ b/Timeline/Services/UserService.cs @@ -150,9 +150,9 @@ namespace Timeline.Services private readonly DatabaseContext _databaseContext; private readonly IJwtService _jwtService; private readonly IPasswordService _passwordService; - private readonly ITencentCloudCosService _cosService; + private readonly IQCloudCosService _cosService; - public UserService(ILogger<UserService> logger, DatabaseContext databaseContext, IJwtService jwtService, IPasswordService passwordService, ITencentCloudCosService cosService) + public UserService(ILogger<UserService> logger, DatabaseContext databaseContext, IJwtService jwtService, IPasswordService passwordService, IQCloudCosService cosService) { _logger = logger; _databaseContext = databaseContext; @@ -301,7 +301,7 @@ namespace Timeline.Services public async Task<string> GetAvatarUrl(string username) { - var exists = await _cosService.Exists("avatar", username); + var exists = await _cosService.ObjectExists("avatar", username); if (exists) return _cosService.GetObjectUrl("avatar", username); else diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index 6491554a..12d60843 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -81,8 +81,8 @@ namespace Timeline }); }); - services.Configure<TencentCosConfig>(Configuration.GetSection(nameof(TencentCosConfig))); - services.AddSingleton<ITencentCloudCosService, TencentCloudCosService>(); + services.Configure<QCloudCosConfig>(Configuration.GetSection(nameof(QCloudCosConfig))); + services.AddSingleton<IQCloudCosService, QCloudCosService>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index c9454ec9..93513bd3 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -12,6 +12,5 @@ <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" /> - <PackageReference Include="Tencent.QCloud.Cos.Sdk.NetCore" Version="5.4.1.1" /> </ItemGroup> </Project> |