七牛_URL签名

1. APP发送Post请求​,只需准备空间名和视频文件名

#pragma mark - 使用同步请求,让php来计算
+ (NSString *)syncPostRequestWithUrlString:(NSString *)urlString videoUrlPrefixPartOne:(NSString *)videoUrlPrefixPartOne
{
    
    //第一步,创建URL
    NSURL *url = [NSURL URLWithString:kQiNiuSpace];
    //第二步,创建请求
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
    [request setHTTPMethod:@"POST"];//设置请求方式为POST,默认为GET
    // 4) 建立请求"数据体",因为要把这个数据体传送给服务器。
    NSString *videoName = [urlString stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"http://%@.bkt.clouddn.com/",videoUrlPrefixPartOne] withString:@""];
    
    
    // 保存下来,后面的方法要用到
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    [userDefault setObject:videoName forKey:@"QiNiuPrivateUrlTool_vidoeName"];
    [userDefault synchronize];
    
    
    NSString *bodyString = [NSString stringWithFormat:@"spacepartone=%@&videoname=%@", videoUrlPrefixPartOne, videoName];
    NSLog(@"数据体字符串:%@", bodyString);
    // 将生成的字符串,用指定的编码转换成数据Data
    NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//    NSLog(@"sg_postBody__%@", body);
    // 5) 设置可变请求的HTTPBody
    [request setHTTPBody:body];
    
    //第三步,连接服务器
    
    NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    
    NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
    
    NSLog(@"sg__responseString:%@",str1);
//    [SGTools showMessage:[NSString stringWithFormat:@"下载中,请勿退出!",str1] duration:5];
    
    return str1;
}


 

2.利用qiniu1space20161222.php生成加密后的下载URL签名: Token

<?php
final class QiNiu 
{
    private $accessKey;
    private $secretKey;
    private $deadLine;
    private $finalToken;

    // 下载的空间地址的前缀
    private $spaceName;
    // 下载的文件名 english_02.mp4
    private $fileName;

    public function __construct($accessKey, $secretKey,$spaceName,$fileName)
    {
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
        $this->spaceName = $spaceName;
        $this->fileName = $fileName;
    }
    public function getAccessKey()
    {
        return $this->accessKey;
    }
    public function getSecretKey()
    {
        return $this->secretKey;
    }
    public function getDeadLine()
    {
        return $this->deadLine;
    }
    public function getFinalToken()
    {
        return $this->finalToken;
    }

    public function getSpaceName()
    {
        return $this->spaceName;
    }
    public function getFileName()
    {
        return $this->fileName;
    }

    /**
     * 对提供的数据进行urlsafe的base64编码。
     *
     * @param string $data 待编码的数据,一般为字符串
     *
     * @return string 编码后的字符串
     * @link http://developer.qiniu.com/docs/v6/api/overview/appendix.html#urlsafe-base64
     */
    public function base64_urlSafeEncode($data)
    {
        $find = array('+', '/');
        $replace = array('-', '_');
        return str_replace($find, $replace, base64_encode($data));
    }

    public function sign($data)
    {
        $hmac = hash_hmac('sha1', $data, $this->secretKey, true);

        $this->finalToken = $this->base64_urlSafeEncode($hmac);

        return $this->accessKey . ':' . $this->finalToken;
    }

    public function privateDownloadUrl($baseUrl, $expires = 20)
    {
        $this->deadLine = time() + $expires;

        $pos = strpos($baseUrl, '?');
        if ($pos !== false) {
            $baseUrl .= '&e=';
        } else {
            $baseUrl .= '?e=';
        }
        $baseUrl .= $this->deadLine;

        $token = $this->sign($baseUrl);
        return "$baseUrl&token=$token";
    }    
}

// $_POST["spacepartone"]   ---     oegnccmnu
// $_POST["videoname"]   ---     fighting.mp4

// http://oegnccmnu.bkt.clouddn.com/fighting.mp4?e=1475503451&token=4lI8KkvqhkxU1zpNIVFOn3YhsHza4jcE3_Aqa298:QQIWGBflFBGHJY_MGo5uydS9k7M=

// 对链接进行签名

$accessKey = 'accessKey';
$secretKey = 'secretKey';

// 构建Auth对象
$auth = new QiNiu($accessKey, $secretKey,$_POST["spacepartone"],$_POST["videoname"]);

// 私有空间中的外链 http://<domain>/<file_key>
// 对链接进行签名
$signedUrl = $auth->privateDownloadUrl('http://'.$auth->getSpaceName().'.bkt.clouddn.com/'.$auth->getFileName());

// http://oegnccmnu.bkt.clouddn.com/fighting.mp4?e=1475503451&token=4lI8KkvqhkxU1zpNIVFOn3YhsHza4jcE3_Aqa298:QQIWGBflFBGHJY_MGo5uydS9k7M=




// 下面是自由发挥
$tmpTimeStamp = $auth->getDeadLine();
$encodeTimeStamp = base64_encode($tmpTimeStamp);

// finalToken
$tmpFinalToken = $auth->getFinalToken();
$encodeFinalToken = base64_encode($tmpFinalToken);

// 使用日期等进行连接
// $currentDate = date("Y-m-d").'vwhm.net'.'beyondlovekeke'.'308829827'.$auth->getSpaceName().$auth->getFileName();
$currentDate = date("Y-m-d").'vwhm.net'.'beyondlovekeke'.'308829827'.$auth->getSpaceName().$auth->getFileName();
$encodeCurrentDate = base64_encode($currentDate);
// 取前5个字符串
$firstFiveEncodeCurrentDateString = substr($encodeCurrentDate, 0,5);


$md5date = md5($currentDate);
$encodemd5date = base64_encode($md5date);

// 取前10个字符串
$firstTenEncodeMd5DateString = substr($encodemd5date, 0,10);


// base64编码
// echo 'http://'.$_POST["spacepartone"].'.bkt.clouddn.com/'.$_POST["videoname"].'?e='.$tmpTimeStamp.'&token='.$accessKey.':'.$tmpFinalToken;

// 连接好的字符串 base64_encode

// 14755531732016-10-04acUzYWGo_Q_ruur98Wm2TjhL3Hs=

// $rawJoinString = $tmpTimeStamp.$currentDate.$tmpFinalToken;

// $encodeString = base64_encode($rawJoinString);

// 新的,base编码后的时间戳+base编码后的日期+base编码后的token
$rawJoinString = $firstTenEncodeMd5DateString.$encodeTimeStamp.'|'.$firstFiveEncodeCurrentDateString.$encodeFinalToken;

// 最后再来一次base编码
$encodeString = base64_encode($rawJoinString);

// 加个服务器的时间戳,目的是:避免用户自己改手机的时间
echo time()."^_^".$encodeString;


3. 在app中, 对php文件 echo 回来的 Token 进行反向解密,  从而拼出下载url

+ (NSString *)encodeUrlString:(NSString *)downloadUrlString videoUrlPrefixPartOne:(NSString *)videoUrlPrefixPartOne
{
    
    NSString *resposnseString = [self syncPostRequestWithUrlString:downloadUrlString videoUrlPrefixPartOne:videoUrlPrefixPartOne];
    
    // 先使用^_^分割,获取前一段的时间戳,如果服务器时间与本机的时间,相差25个小时,则说明,用户自己乱设置了时间!
    NSArray *tmpArr = [resposnseString componentsSeparatedByString:@"^_^"];
    long long serverTimeStamp = [[tmpArr firstObject] longLongValue];
//    1479040800
    
    
    NSString *rawResponseStr = [tmpArr lastObject];
    
    
    
    NSTimeInterval clientTimeStamp = [[NSDate date] timeIntervalSince1970];
    NSLog(@"sg__client:%f",clientTimeStamp);
    NSLog(@"sg__client:%f",fabs(clientTimeStamp));
    
    double gap = fabs(fabs(clientTimeStamp) - serverTimeStamp);
    NSLog(@"sg__gap:%f",fabs(fabs(clientTimeStamp) - serverTimeStamp));
    // 时间戳合法,即在+ -24个小时以内 
    if (gap < 24 * 3600) {
        return [self decodeResponseString:rawResponseStr videoUrlPrefixPartOne:videoUrlPrefixPartOne];
    }
    // 提示:客户端时间非法
    [SGTools showMessage:@"客户端时间不正确" duration:10];
    return @"";
}


// 反向解密 php加密返回的字符串
+ (NSString *)decodeResponseString:(NSString *)responseString videoUrlPrefixPartOne:(NSString *)videoUrlPrefixPartOne
{
    NSString *rawJoinString = [responseString base64DecodedString];
//    NSLog(@"sg_rawJoinString__%@",rawJoinString);
    // $encodeTimeStamp.$firstFiveEncodeCurrentDateString.$encodeFinalToken;
    // 先算出
    NSArray *tmpArr = [rawJoinString componentsSeparatedByString:@"|"];
    
    
//    NSString *encodeMd5Date = [self encodeMd5Date];
//    NSString *timeStamp = [encodeTimeStamp stringByReplacingOccurrencesOfString:encodeMd5Date withString:@""];
//    NSString *md5AndTimeStamp = [timeStamp base64DecodedString];
    
    
    
    
    NSString *encodeTimeStamp = [tmpArr[0] substringFromIndex:10];
    NSString *timeStamp = [encodeTimeStamp base64DecodedString];
    
    
 
    timeStamp = [NSString stringWithFormat:@"%lld",[timeStamp longLongValue]];
    
//    NSLog(@"sg_timeStamp__%@",timeStamp);
    
    NSString *encodeFinalToken = [tmpArr[1] substringFromIndex:5];
    NSString *finalToken = [encodeFinalToken base64DecodedString];
//    NSLog(@"sg_finalToken__%@",finalToken);
    
    
    
    
    // 根据用户上次选择的,展示
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSString *videoName = [userDefault objectForKey:@"QiNiuPrivateUrlTool_vidoeName"];
    [userDefault synchronize];
    // http://oegnccmnu.bkt.clouddn.com/fighting.mp4?e=1475503451&token=4lI8KkvqhkxU1zpNIVFOn3YhsHza4jcE3_Aqa298:QQIWGBflFBGHJY_MGo5uydS9k7M=
    NSString *plainDownloadUrlString = [NSString stringWithFormat:@"%@%@?e=%@&token=%@:%@",[NSString stringWithFormat:@"http://%@.bkt.clouddn.com/",videoUrlPrefixPartOne],videoName,timeStamp,kQiNiuAccessKey,finalToken];
    
    
    
//    NSLog(@"sg_plainDownloadUrlString__%@",plainDownloadUrlString);
    return plainDownloadUrlString;
}