七牛回调验证(java,php源码)

1,七牛的客户可以对七牛回调过来的信息做验证。防止其他网站的信息冒充七牛。

2,安全性

*由于回调地址是公网可任意访问的,回调服务如何确认一次回调是合法的呢?
七牛云存储在回调时会对请求数据签名,并将结果包含在请求头Authorization字段中,示例如下:
Authorization:QBox iN7NgwM31j4-BZacMjPrOQBs34UG1maYCAQmhdCV:tDK-3f5xF3SJYEAwsll5g=
其中QBox为固定值,iN7Ngw…dCV为用户的Accesskey,tDK-3f…5g=为签名结果(encoded_data)
回调服务器可以通过以下方法验证其合法性:
获取AUTHORIZATION字段值中的签名结果部分encoded_data
根据Accesskey选取正确的SecretKey
获取明文:data = Request.URL.Path +”\n” +Request.Body
部分语言或框架无法直接获取请求body的原始数据,在自行拼接时应当注意,body中的数据是经过URL编码的
采用HMAC-SHA1签名算法,对明文data签名,秘钥为SecretKey,比较签名结果是否与Authorization中的encoded_data字段相同,如相同则表明这是一个合法的回调请求
以PHP语言为示例,验证代码如下:*

/**
*C('accessKey')取得 AccessKey
*C('secretKey')取得 SecretKey  
*callback.php 为回调地址的Path部分  
*file_get_contents('php://input')获取RequestBody,其值形如:  
*name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2\
*&location=Shanghai&price=1500.00&uid=123
*/
function IsQiniuCallback(){
    $authstr = $_SERVER['HTTP_AUTHORIZATION'];
    if(strpos($authstr,"QBox ")!=0){
        return false;
    }
    $auth = explode(":",substr($authstr,5));
    if(sizeof($auth)!=2||$auth[0]!=C('accessKey')){
        return false;
    }
    $data = "/callback.php\n".file_get_contents('php://input');
    return URLSafeBase64Encode(hash_hmac('sha1',$data,C("secretKey"), true)) == $auth[1];
}

注意:如果回调数据包含用户的敏感数据,建议回调地址使用HTTPS协议

3,java源码

package com.qiniu.isValidCallback;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.qiniu.util.Auth;
import com.qiniu.util.StringUtils;

public class IsValidCallback extends HttpServlet {

    /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String ak = "****";
        String sk = "****";

        Auth auth = Auth.create(ak,sk);     
        ServletContext context = getServletContext( );  

        String charset = request.getCharacterEncoding();        
        String Authorization = request.getHeader("Authorization");
        String contentType = request.getHeader("Content-Type");             
        String line = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }               
        String url = "https://14190f2ca55e.b.passageway.io/IsValidCallback/servlet/IsValidCallback";

        boolean check = false; 

        check= auth.isValidCallback(Authorization,url,StringUtils.utf8Bytes(sb.toString()),contentType);

        String authorization2 = "QBox " + auth.signRequest(url, StringUtils.utf8Bytes(sb.toString()), contentType);

        context.setAttribute("Authorization", Authorization);
        context.setAttribute("Authorization", Authorization);
        context.setAttribute("authorization2", authorization2);
        context.setAttribute("body", sb.toString());
        context.setAttribute("contentType", contentType);                   
        if(check){
            context.log("签名通过 ok!");
            context.setAttribute("check", "签名通过 ok");
        }else{
            context.log("No ok!");
            context.setAttribute("check", "no ok");
        }       

        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");        

        String out = "{\"success\":\"ok\",\"name\":\"test1\"}";

        response.getOutputStream().print(out);;

    }
    /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

你可能感兴趣的:(七牛回调验证(java,php源码))