python django 使用記錄

主要想用web搭建個聲紋識別的接口,目前正在學python,比較敏捷,django是其中使用廣泛的文本框架,下面是使用過程中遇到的問題記錄

1、任意ip訪問

1)settings中

ALLOWED_HOSTS = ['*']

2)

python manage.py runserver 0.0.0.0:8000


2、js提交表達問題

Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.


這個是csrf驗證不通過,爲什麼需要csrf:

1.用戶C打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼請求登錄網站A;

2.在用戶信息通過驗證後,網站A產生Cookie信息並返回給瀏覽器,此時用戶登錄網站A成功,可以正常發送請求到網站A;

3.用戶未退出網站A之前,在同一瀏覽器中,打開一個TAB頁訪問網站B;

4.網站B接收到用戶請求後,返回一些攻擊性代碼,併發出一個請求要求訪問第三方站點A;

5.瀏覽器在接收到這些攻擊性代碼後,根據網站B的請求,在用戶不知情的情況下攜帶Cookie信息,向網站A發出請求。網站A並不知道該請求其實是由B發起的,所以會根據用戶C的Cookie信息以C的權限處理該請求,導致來自網站B的惡意代碼被執行。

預防csrf攻擊簡單可行的方法就是在客戶端網頁上添加隨機數,在服務器端進行隨機數驗證,以確保該請求是用戶允許的。Django也是通過這個方法來防禦csrf攻擊的

參考鏈接 http://www.jianshu.com/p/a178f08d9389

解決辦法:

1)

表單中加入{% csrf_token %}:

<form name="enrollForm" action="/enroll-audio-over"
                  οnsubmit="return UploadRecord()" method="post">
                 {% csrf_token %}
                <div style="margin-top: 30px">
                    <input id="username" type="text" placeholder="????..." >
                    <input type="submit" value="????"/>
                </div>
 </form>

2)

不要用render,要使用render_to_response

3)

過濾csrf檢驗:@csrf_exempt


3、django中執行shell腳本並返回執行結果到頁面上

    (status, output) = commands.getstatusoutput('echo "test shell"')
    context = {}
    context['status'] = status
    context['output'] = output
    return render(request, 'index.html', context)


4、onsubmit的bug,UploadRecord()的返回值不能影響表單的提交

<form name="enrollForm" action="/enroll-audio-over"
     οnsubmit="return UploadRecord();" method="post">
    {% csrf_token %}
     <div style="margin-top: 30px">
          <input id="username" type="text" placeholder="你的姓名..." >
          <input type="submit" value="上傳錄音"/>
     </div>
</form>

在網上檢索沒找到合理的解釋,自己分析的結果:如果UploadRecord()只是簡單的檢測輸入的合理正確性,就沒問題;如果其中做了網頁的跳轉或者提交服務器的操作就會有問題。

處理辦法:避免在一個表單裏做多個提交,可以直接用js響應按鍵的點擊,然後再在按鍵的響應結束後做提交或跳



5、html5錄音

感覺也是挺坑的,調用不同瀏覽器的接口,AudioAPI的默認採樣頻率是由實現定義,且不能修改的, Firefox使用44100(筆記本的是48000),而Chrome使用了最大采樣比率96000,而每個採樣位數獲取不到:



所以想要修改其他的採樣率就得在這個基礎上下采樣,想要更高的採樣就不行了,下面是結合同事在網上找的代碼再修改的,主要是聲道數,及下采樣的修改。

1.js

(function (window) {  
    window.URL = window.URL || window.webkitURL;  
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;  
  
    var HZRecorder = function (stream, config) {  
        config = config || {};
        config.sampleBits = config.sampleBits || 16;     
        config.sampleRate = config.sampleRate || (8000);   
        // config.sampleBits = 16;      //???? 8, 16
        // config.sampleRate = 8000;
          
        var audioContext = window.AudioContext
            || window.webkitAudioContext  // Chrome
            || window.mozAudioContext  // Firefox
            || window.msAudioContext;

        var context = new audioContext();
  
        var audioInput = context.createMediaStreamSource(stream);  
           
        var volume = context.createGain();  
        audioInput.connect(volume);  
   
        var bufferSize = 4096;  
  
        // 創建聲音的緩存節點 第二和第三指輸入和輸出的聲道數  
        // var recorder = context.createScriptProcessor(bufferSize, 2, 2);
        var recorder = context.createScriptProcessor(bufferSize, 1, 1);

        var audioData = {  
            size: 0          //錄音文件長度 
            , buffer: []       
            , inputSampleRate: context.sampleRate    
            , inputSampleBits: 16       
            , outputSampleRate: config.sampleRate    
            , outputSampleBits: config.sampleBits    

            , input: function (data) {  
                this.buffer.push(new Float32Array(data));  
                this.size += data.length;  
            }

            //先合併,在下采樣
            , compress: function () {
                //  合併 
                var data = new Float32Array(this.size);  
                var offset = 0;  
                for (var i = 0; i < this.buffer.length; i++) {  
                    data.set(this.buffer[i], offset);  
                    offset += this.buffer[i].length;  
                }  
                
                //  下采樣
                var compression = (this.inputSampleRate / this.outputSampleRate);
                var length = parseInt(data.length / compression);
                var result = new Float32Array(length);
                var index = 0;
                while (index < length) {
                    offset = parseInt(index * compression);
                    result[index] = data[offset];
                    index++;
                }
                return result;  
            }

            , encodeWAV: function () {  
                var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);  
                var sampleBits = Math.min(this.inputSampleBits, this.outputSampleBits);
                var bytes = this.compress();  
                var dataLength = bytes.length * (sampleBits / 8);  
                var buffer = new ArrayBuffer(44 + dataLength);  
                var data = new DataView(buffer);  
  
                var channelCount = 1;
                var offset = 0;  
  
                var writeString = function (str) {  
                    for (var i = 0; i < str.length; i++) {  
                        data.setUint8(offset + i, str.charCodeAt(i));  
                    }  
                };  
                  
                // ?????????   
                writeString('RIFF'); offset += 4;  
                // ??????????????,?????-8   
                data.setUint32(offset, 36 + dataLength, true); offset += 4;  
                // WAV????  
                writeString('WAVE'); offset += 4;  
                // ??????   
                writeString('fmt '); offset += 4;  
                // ????,??? 0x10 = 16   
                data.setUint32(offset, 16, true); offset += 4;  
                // ???? (PCM??????)   
                data.setUint16(offset, 1, true); offset += 2;  
                // ???   
                data.setUint16(offset, channelCount, true); offset += 2;  
                // ???,?????,???????????   
                data.setUint32(offset, sampleRate, true); offset += 4;  
                // ??????? (???????) ???????????????/8   
                data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;  
                // ?????? ????????? ???????????/8   
                data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;  
                // ???????   
                data.setUint16(offset, sampleBits, true); offset += 2;  
                // ?????   
                writeString('data'); offset += 4;
                // ??????,??????-44   
                data.setUint32(offset, dataLength, true); offset += 4;  
                // ??????   
                if (sampleBits === 8) {  
                    for (var i = 0; i < bytes.length; i++, offset++) {  
                        var s = Math.max(-1, Math.min(1, bytes[i]));  
                        var val = s < 0 ? s * 0x8000 : s * 0x7FFF;  
                        val = parseInt(255 / (65535 / (val + 32768)));  
                        data.setInt8(offset, val, true);  
                    }  
                } else {  
                    for (var i = 0; i < bytes.length; i++, offset += 2) {  
                        var s = Math.max(-1, Math.min(1, bytes[i]));  
                        data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);  
                    }  
                }  
  
                return new Blob([data], { type: 'audio/wav' });  
            }  
        };  
  
        //????  
        this.start = function () {  
            audioInput.connect(recorder);  
            recorder.connect(context.destination);  
        };  
  
        //??  
        this.stop = function () {  
            recorder.disconnect();  
        };  
  
        //??????  
        this.getBlob = function () {  
            this.stop();  
            return audioData.encodeWAV();  
        };  
  
        //??  
        this.play = function (audio) {  
            audio.src = window.URL.createObjectURL(this.getBlob());  
        };  
  
        //??  
        this.upload = function (url, username, callback) {
            var fd = new FormData();  
            fd.append('userName', username);
            fd.append('audioData', this.getBlob());
            var xhr = new XMLHttpRequest();  
            if (callback) {  
                xhr.upload.addEventListener('progress', function (e) {  
                    callback('uploading', e);  
                }, false);  
                xhr.addEventListener('load', function (e) {
                    callback('????', e);
                }, false);  
                xhr.addEventListener('error', function (e) {
                    callback('error', e);
                }, false);  
                xhr.addEventListener('abort', function (e) {
                    callback('cancel', e);  
                }, false);  
            }  
            xhr.open('POST', url);  
            xhr.send(fd);  
        };  
  
        //????  
        recorder.onaudioprocess = function (e) {  
            audioData.input(e.inputBuffer.getChannelData(0));  
            //record(e.inputBuffer.getChannelData(0));  
        };  
  
    };

    //????  
    HZRecorder.throwError = function (message) {  
        throw new function () { this.toString = function () { return message; };};  
    };

    //??????  
    HZRecorder.canRecording = (navigator.getUserMedia != null);

    //?????  
    HZRecorder.get = function (callback, config) {  
        if (callback) {  
            if (navigator.getUserMedia) {  
                navigator.getUserMedia(  
                    { audio: true } //?????

                    , function (stream) {  
                        var rec = new HZRecorder(stream, config);  
                        callback(rec);  
                    }

                    , function (error) {  
                        switch (error.code || error.name) {  
                            case 'PERMISSION_DENIED':  
                            case 'PermissionDeniedError':  
                                HZRecorder.throwError('?????????');  
                                break;  
                            case 'NOT_SUPPORTED_ERROR':  
                            case 'NotSupportedError':  
                                HZRecorder.throwError('<a href="http://www.it165.net/edu/ewl/" target="_blank" class="keylink">???</a>????????');  
                                break;  
                            case 'MANDATORY_UNSATISFIED_ERROR':  
                            case 'MandatoryUnsatisfiedError':  
                                HZRecorder.throwError('????????????');  
                                break;  
                            default:  
                                HZRecorder.throwError('????????????:' + (error.code || error.name));  
                                break;  
                        }  
                    });  
            } else {  
                HZRecorder.throwErr('??<a href="http://127.0.0.1" target="_blank" class="keylink">???</a>????????'); return;
            }  
        }
    };  
    window.HZRecorder = HZRecorder;

})(window);  
2.js
/* ?? */
var recorder;  
var audio = document.querySelector('audio');
show = document.getElementById("show")
var start = false
var stop = true

var setIntervalHandler ;
function startRecording() {
    start = true;
    recorderTime = 0;
    function show1(){
        recorderTime += 1;
        show.innerHTML="?????..."+recorderTime+"?"
    }
    if (setIntervalHandler!=null){
        clearInterval(setIntervalHandler)
    }

    setIntervalHandler = setInterval(show1,1000);

    show.innerHTML="?????..."
    HZRecorder.get(function (rec) {
        recorder = rec;  
        recorder.start();  
    });  
}  

function obtainRecord(){  
    var record = recorder.getBlob();  
};
  
function stopRecord(){
    if(start == false){
       show.innerHTML = "????";
        return
    }
    clearInterval(setIntervalHandler)
    stop = true
    recorder.stop();
    show.innerHTML = "?????";
};  
  
function playRecord(){
    if(start == false){
       show.innerHTML = "????";
        return
    }
    clearInterval(setIntervalHandler)
    show.innerHTML = "????";
    stop = true
    recorder.play(audio);
};  

function UploadRecord(){
    if(start == false){
        show.innerHTML = "????";
        return false;
    }
    if(stop == false){
        show.innerHTML = "??????"
        return false;
    }
    clearInterval(setIntervalHandler)
    var username = $("#username").val();
    if (username == ""){
        show.innerHTML = "?????"
        return false;
    }else{
         recorder.upload("upload/", username, function (result) {
             // show.innerHTML = result
             // console.log(result)
             // window.location = "index.html"
             return true;
         })
         //return false;
    }
}

6、web audio api 手機端不能訪問

需要使用https服務纔可以

參考鏈接:http://www.jb51.net/article/51806.htm

在 CentOS 上

yum install stunnel

openssl req -new -x509 -days 365 -nodes -out vpsee.pem -keyout vpsee.pem

chmod 600 vpsee.pem

生成https文件:vi https

-----------------------

cert = vpsee.pem
debug = 7
foreground = yes

[https]
accept = 443
connect = 80
---------------------

啓動服務:

stunnel https

django終端執行:

python manage.py runserver 0.0.0.0:80

然後就ok了。目前蘋果手機及ie瀏覽器還跑不了






發佈了55 篇原創文章 · 獲贊 18 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章