腾讯官方没有提供C#版的,没办法自己根据java版改写了一个,这里面的坑花了我20多个小时,所以记录下
<%@ WebHandler Language="C#" Class="YZCosServices" %>
using System;
using System.Web;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.Collections.Generic;
using BPM;
using BPM.Client;
using YZSoft.Web.DAL;
using Newtonsoft.Json.Linq;
public class YZCosServices : YZServiceHandler
{
public static string SecretId = "xx";
public static string SecretKey = "xx";
public static string bucket = "app-1255562498";
public static string region = "chengdu";
public static int durationSeconds = 1800;
public JObject GetAuth(HttpContext context)
{
JObject credential = new JObject();;
try
{
YZRequest request = new YZRequest(context);
SortedList<String, Object> config = new SortedList<String, Object>();
// 固定密钥
config.Add("SecretId", SecretId);
// 固定密钥
config.Add("SecretKey", SecretKey);
// 临时密钥有效时长,单位是秒
config.Add("durationSeconds", durationSeconds);
// 换成你的 bucket
config.Add("bucket", bucket);
// 换成 bucket 所在地区
config.Add("region", region);
// 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的目录,例子:* 或者 a/* 或者 a.jpg
config.Add("allowPrefix", "*");
// 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
String[] allowActions = new String[] {
"*"
/*
// 简单上传
"name/cos:PutObject",
// 分片上传
"name/cos:InitiateMultipartUpload",
"name/cos:ListMultipartUploads",
"name/cos:ListParts",
"name/cos:UploadPart",
"name/cos:CompleteMultipartUpload"
*/
};
config.Add("allowActions", allowActions);
string result = getCredential(config);
credential.Add("status", true);
credential.Add("data", result);
}
catch (Exception e) {
credential.Add("status", false);
credential.Add("errMsg"+e.Message);
}
return credential;
}
public static string getCredential(SortedList<string, object> config) {
SortedList<string, object> params1 = new SortedList<string, object>();
if (config.ContainsKey("policy"))
{
string policy = (string)config["policy"];
if (policy != null)
{
params1.Add("Policy", policy);
}
else
{
params1.Add("Policy", getPolicy(config));
}
}
else {
params1.Add("Policy", getPolicy(config));
}
int durationSeconds = 1800;
if (config["durationSeconds"] != null) {
durationSeconds = (Int32) config["durationSeconds"];
}
params1.Add("DurationSeconds", durationSeconds);
params1.Add("Name", "cos-sts-donet");
params1.Add("Action", "GetFederationToken");
params1.Add("Version", "2018-08-13");
params1.Add("Region", "ap-guangzhou");
string host = "sts.tencentcloudapi.com";
string path = "/";
string result = null;
try {
result = send(params1, (string) config["SecretId"],
config["SecretKey"].ToString(),
"POST", host, path);
/*
JObject jsonResult = new JObject( );
JObject data = (JObject)jsonResult["Response"];
if (data == null) {
data = jsonResult;
}
Int64 expiredTime = Convert.ToInt64(data["ExpiredTime"]);
data.Add("startTime", expiredTime - durationSeconds);
return downCompat(data);
*/
} catch (Exception e) {
throw new Exception("result = " + result, e);
}
return result;
}
public static string getPolicy(List<Scope> scopes) {
if(scopes == null || scopes.Count == 0)return null;
STSPolicy stsPolicy = new STSPolicy();
stsPolicy.addScope(scopes);
return stsPolicy.ToString();
}
// v2接口的key首字母小写,v3改成大写,此处做了向下兼容
private static JObject downCompat(JObject resultJson) {
JObject dcJson = new JObject();
foreach (var item in dcJson)
{
object value = item.Value;
if (value is JObject)
{
dcJson.Add(headerToLowerCase(item.Key), downCompat((JObject)value));
}
else
{
string newKey = "Token" == item.Key ? "sessionToken" : headerToLowerCase(item.Key);
dcJson.Add(newKey, item.Value);
}
}
return dcJson;
}
private static string headerToLowerCase(string source) {
return source.Substring(0 - 1).ToLower() + source.Substring(1);
}
private static string getPolicy(SortedList<string, object> config) {
string bucket = (string) config["bucket"];
string region = (string) config["region"];
string allowPrefix = (string) config["allowPrefix"];
string[] allowActions = (string[]) config["allowActions"];
JObject principal = new JObject();
principal.Add("qcs", "*");
int lastSplit = bucket.LastIndexOf("-");
string shortBucketName = bucket.Substring(0, lastSplit);
string appId = bucket.Substring(lastSplit + 1);
string resource = string.Format("qcs::cos:{0}:uid/{1}:prefix//{2}/{3}/{4}",
region, appId, appId, shortBucketName, allowPrefix);
JArray actions = new JArray();
foreach(var action in allowActions) {
actions.Add(action);
}
JObject policy = new JObject();
JObject statement = new JObject();
statement.Add("principal", principal);
statement.Add("resource", resource);
statement.Add("effect", "allow");
statement.Add("action", actions);
policy.Add("statement", statement);
policy.Add("version", "2.0");
return Newtonsoft.Json.JsonConvert.SerializeObject(policy);
}
/// <summary>
/// 准备发送请求
/// </summary>
/// <param name="params1"></param>
/// <param name="secretId"></param>
/// <param name="secretKey"></param>
/// <param name="requestMethod"></param>
/// <param name="requestHost"></param>
/// <param name="requestPath"></param>
/// <returns></returns>
public static string send(SortedList<string, object> params1, string secretId,
string secretKey, string requestMethod, string requestHost,
string requestPath) {
if (!params1.ContainsKey("SecretId"))
params1.Add("SecretId", secretId);
if (!params1.ContainsKey("Nonce"))
params1.Add("Nonce",new Random().Next(Int32.MaxValue));
//params1.Add("Nonce",829042144);
if (!params1.ContainsKey("Timestamp"))
params1.Add("Timestamp", ConvertDataTimeToLong(DateTime.Now) / 1000);
// params1.Add("Timestamp", 1551241700);
params1.Remove("Signature");
string plainText = makeSignPlainText(params1, requestMethod,
requestHost, requestPath);
string signatureMethod = "HmacSHA1";
if (params1.ContainsKey("SignatureMethod") && params1["SignatureMethod"].ToString() == "HmacSHA256")
{
signatureMethod = "HmacSHA256";
}
String signStr = sign(plainText, secretKey, signatureMethod);
System.IO.File.WriteAllLines(@"d:\test2.txt", new string[]{ plainText+"\r\n"+signStr}, Encoding.UTF8);
params1.Add("Signature", signStr);
string url = "https://" + requestHost + requestPath;
return sendRequest(url, params1, requestMethod);
}
/// <summary>
/// 发送请求
/// </summary>
/// <param name="url"></param>
/// <param name="requestParams"></param>
/// <param name="requestMethod"></param>
/// <returns></returns>
public static String sendRequest(String url, SortedList<string, object> requestParams, String requestMethod) {
String result = "";
String paramStr = "";
foreach (var item in requestParams) {
if (!string.IsNullOrEmpty(paramStr)) {
paramStr += '&';
}
paramStr += item.Key + '='
+XUrlEncode(item.Value.ToString());
}
if (requestMethod=="GET") {
if (url.IndexOf('?') > 0) {
url += '&' + paramStr;
} else {
url += '?' + paramStr;
}
}
string requestUrl = url;
String BOUNDARY = "---------------------------"
+ EnMD5(ConvertDataTimeToLong(DateTime.Now)+"")
.Substring(0, 15);
System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckCertificate);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(requestUrl);
request.Accept = "*/*";
request.KeepAlive = true;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)";
// 设置链接主机超时时间
request.Timeout = 90000;
request.ReadWriteTimeout = 90000;
request.Expect = null;
System.Net.WebProxy proxy = new System.Net.WebProxy(); //定義一個網關對象
proxy.Address = new Uri("http://127.0.0.1:8888"); //網關服務器:端口
request.Proxy = proxy;
if (requestMethod=="POST") {
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] buffer = Encoding.UTF8.GetBytes(paramStr);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
request.GetRequestStream().Close();
}
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
System.IO.Stream stream = response.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(stream, Encoding.UTF8);
result = sr.ReadToEnd();
return result;
}
/// <summary>
/// 天坑,这里urlcode的到的转码字母是小写,java平台得到的转码字母是大写,所以需要转换成小写。
/// 当然腾讯运平台估计也是用的小写
/// 不然验证不会通不过。
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string XUrlEncode(string str)
{
StringBuilder builder = new StringBuilder();
foreach (char c in str)
{
if (HttpUtility.UrlEncode(c.ToString()).Length > 1)
{
builder.Append(HttpUtility.UrlEncode(c.ToString(),System.Text.Encoding.UTF8).ToUpper());
}
else
{
builder.Append(c);
}
}
return builder.ToString();
}
/// <summary>
/// 获取unix的时间戳
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static long ConvertDataTimeToLong(DateTime dt)
{
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
TimeSpan toNow = dt.Subtract(dtStart);
long timeStamp = toNow.Ticks;
timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
return timeStamp;
//return 1551183028000l;
}
/// <summary>
/// md5签名
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string EnMD5(string text) {
System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();
byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(text));
return Convert.ToBase64String(data);
}
/// <summary>
/// 构建待加密的明文文本
/// </summary>
/// <param name="requestParams"></param>
/// <param name="requestMethod"></param>
/// <param name="requestHost"></param>
/// <param name="requestPath"></param>
/// <returns></returns>
public static String makeSignPlainText(SortedList<String, Object> requestParams, String requestMethod, String requestHost, String requestPath) {
String retStr = "";
retStr += requestMethod;
retStr += requestHost;
retStr += requestPath;
retStr += buildParamStr(requestParams, requestMethod);
return retStr;
}
/// <summary>
/// 检测证书
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="errors"></param>
/// <returns></returns>
private static bool CheckCertificate(object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors errors)
{
return true;
}
/// <summary>
/// 构建待加密的明文文本
/// </summary>
/// <param name="requestParams"></param>
/// <param name="requestMethod"></param>
/// <returns></returns>
protected static String buildParamStr(SortedList<String, Object> requestParams, String requestMethod) {
String retStr = "";
foreach(var item in requestParams) {
String value = item.Value.ToString();
//排除上传文件的参数
if("POST"==requestMethod && (! string.IsNullOrEmpty(value)) && value.Substring(0, 1)=="@"){
continue;
}
if (retStr.Length==0) {
retStr += '?';
} else {
retStr += '&';
}
retStr += item.Key.Replace("_", ".") + '=' + value;
}
return retStr;
}
/**
* 签名
* @author [email protected]
*
* @param signStr 被加密串
* @param secret 加密密钥
* @param signatureMethod 签名算法
*
* @return 签名结果
*/
public static String sign(String signStr, String secret, String signatureMethod)
{
byte[] keyByte = Encoding.UTF8.GetBytes(secret);
byte[] messageBytes = Encoding.UTF8.GetBytes(signStr);
if (signatureMethod == "HmacSHA256")
{
using (var hmacsha256 = new System.Security.Cryptography.HMACSHA256(keyByte))
{
hmacsha256.Initialize();
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
} else {
using (var hmacsha1 = new System.Security.Cryptography.HMACSHA1(keyByte))
{
hmacsha1.Initialize();
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
}
public class STSPolicy {
private List<Scope> scopes = new List<Scope>();
public STSPolicy() {
}
public void addScope(List<Scope> scopes) {
if (scopes != null) {
foreach (Scope scope in scopes) {
this.scopes.Add(scope);
}
}
}
public void addScope(Scope scope) {
this.scopes.Add(scope);
}
private SortedList<string,Object> createElement(Scope scope) {
SortedList<string,Object> principal = new SortedList<string,Object>();
List<Object> qcs = new List<Object>();
qcs.Add("*");
principal.Add("qcs", qcs);
List<Object> resources = new List<Object>();
resources.Add(scope.getResource());
List<Object> actions = new List<Object>();
actions.Add(scope.getAction());
SortedList<string,Object> element = new SortedList<string,Object>();
element.Add("principal", principal);
element.Add("resource", resources);
element.Add("effect", "allow");
element.Add("action", actions);
System.IO.File.WriteAllLines(@"d:\test1.txt", new string[]{ Newtonsoft.Json.JsonConvert.SerializeObject(element)}, Encoding.UTF8);
return element;
}
public override String ToString() {
SortedList<string,Object> policy = new SortedList<string,Object>();
policy.Add("version", "2.0");
List<Object> statement = new List<Object>();
if (scopes.Count > 0) {
foreach (Scope scope in scopes) {
statement.Add(createElement(scope));
}
policy.Add("statement", statement);
}
return Newtonsoft.Json.JsonConvert.SerializeObject(policy);
}
}
public class Scope {
private String action;
private String bucket;
private String region;
private String sourcePrefix;
/**
*
* @param action 操作名称,如 "name/cos:PutObject"
* @param bucket 存储桶名称,格式:test-1250000000
* @param region 园区名称,如 ap-guangzhou
* @param prefix 拼接 resource 字段所需的 key 前缀,客户端 SDK 默认传固定文件名如 "dir/1.txt",支持 * 结尾如 "dir/*"
*/
public Scope(String action, String bucket, String region, String sourcePrefix) {
this.action = action;
this.bucket = bucket;
this.region = region;
this.sourcePrefix = sourcePrefix;
}
public void setBucket(String bucket) {
this.bucket = bucket;
}
public void setRegion(String region) {
this.region = region;
}
public void setAction(String action) {
this.action = action;
}
public void setResourcePrefix(String sourcePrefix) {
this.sourcePrefix = sourcePrefix;
}
public String getAction() {
return this.action;
}
public String getResource() {
int index = bucket.LastIndexOf('-');
String appid = bucket.Substring(index + 1).Trim();
String bucketName = bucket.Substring(0, index).Trim();
if(!sourcePrefix.StartsWith("/")) {
sourcePrefix = '/' + sourcePrefix;
}
StringBuilder resource = new StringBuilder();
resource.Append("qcs::cos")
.Append(':')
.Append(region)
.Append(':')
.Append("uid/").Append(appid)
.Append(':')
.Append("prefix//").Append(appid).Append('/').Append(bucketName)
.Append(sourcePrefix);
return resource.ToString();
}
}
}