![](/img/trans.png)
[英]Django CSRF check failing in JavaScript post request like a form submit
[英]JavaScript post request like a form submit
我正在嘗試將瀏覽器定向到不同的頁面。 如果我想要一個 GET 請求,我可能會說
document.location.href = 'http://example.com/q=a';
但是除非我使用 POST 請求,否則我嘗試訪問的資源不會正確響應。 如果這不是動態生成的,我可能會使用 HTML
<form action="http://example.com/" method="POST">
<input type="hidden" name="q" value="a">
</form>
然后我會從 DOM 提交表單。
但我真的想要 JavaScript 代碼讓我說
post_to_url('http://example.com/', {'q':'a'});
最好的跨瀏覽器實現是什么?
編輯
對不起,我不清楚。 我需要一個改變瀏覽器位置的解決方案,就像提交表單一樣。 如果這對XMLHttpRequest是可能的,那么它並不明顯。 而且這個應該不是異步的,也不是用XML,所以Ajax不是答案。
<input>
並提交/**
* sends a request to the specified url from a form. this will change the window location.
* @param {string} path the path to send the post request to
* @param {object} params the parameters to add to the url
* @param {string} [method=post] the method to use on the form
*/
function post(path, params, method='post') {
// The rest of this code assumes you are not using a library.
// It can be made less verbose if you use one.
const form = document.createElement('form');
form.method = method;
form.action = path;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
例子:
post('/contact/', {name: 'Johnny Bravo'});
編輯:由於這已經得到了如此多的支持,我猜人們會大量復制粘貼它。 所以我添加了hasOwnProperty
檢查來修復任何無意中的錯誤。
這將是使用jQuery所選答案的一個版本。
// Post to the provided URL with the specified parameters.
function post(path, parameters) {
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", path);
$.each(parameters, function(key, value) {
var field = $('<input></input>');
field.attr("type", "hidden");
field.attr("name", key);
field.attr("value", value);
form.append(field);
});
// The form needs to be a part of the document in
// order for us to be able to submit it.
$(document.body).append(form);
form.submit();
}
使用此答案中提供的createElement
函數,這是必要的,因為IE 破壞了使用document.createElement
正常創建的元素的 name 屬性:
function postToURL(url, values) {
values = values || {};
var form = createElement("form", {action: url,
method: "POST",
style: "display: none"});
for (var property in values) {
if (values.hasOwnProperty(property)) {
var value = values[property];
if (value instanceof Array) {
for (var i = 0, l = value.length; i < l; i++) {
form.appendChild(createElement("input", {type: "hidden",
name: property,
value: value[i]}));
}
}
else {
form.appendChild(createElement("input", {type: "hidden",
name: property,
value: value}));
}
}
}
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
Rakesh Pai 的回答很棒,但是當我嘗試發布一個帶有名為submit
的字段的表單時,我(在Safari 中)出現了一個問題。 例如, post_to_url("http://google.com/",{ submit: "submit" } );
. 我已經稍微修補了這個函數來繞過這個可變空間碰撞。
function post_to_url(path, params, method) {
method = method || "post";
var form = document.createElement("form");
//Move the submit function to another variable
//so that it doesn't get overwritten.
form._submit_function_ = form.submit;
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form._submit_function_(); //Call the renamed function.
}
post_to_url("http://google.com/", { submit: "submit" } ); //Works!
不可以。您不能像提交表單那樣使用 JavaScript 發布請求。
您可以擁有一個 HTML 格式的表單,然后使用 JavaScript 提交它。 (正如本頁多次解釋的那樣)。
您可以自己創建 HTML,不需要 JavaScript 來編寫 HTML。 如果有人這么建議,那將是愚蠢的。
<form id="ninja" action="http://example.com/" method="POST">
<input id="donaldduck" type="hidden" name="q" value="a">
</form>
您的函數只會按照您想要的方式配置表單。
function postToURL(a,b,c){
document.getElementById("ninja").action = a;
document.getElementById("donaldduck").name = b;
document.getElementById("donaldduck").value = c;
document.getElementById("ninja").submit();
}
然后,像這樣使用它。
postToURL("http://example.com/","q","a");
但我會忽略這個功能而只是去做。
document.getElementById('donaldduck').value = "a";
document.getElementById("ninja").submit();
最后,樣式決定在 ccs 文件中。
#ninja{
display:none;
}
我個人認為表格應該按名稱尋址,但現在這並不重要。
這是 rakesh 的答案,但支持數組(這在表單中很常見):
普通的javascript:
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
var addField = function( key, value ){
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value );
form.appendChild(hiddenField);
};
for(var key in params) {
if(params.hasOwnProperty(key)) {
if( params[key] instanceof Array ){
for(var i = 0; i < params[key].length; i++){
addField( key, params[key][i] )
}
}
else{
addField( key, params[key] );
}
}
}
document.body.appendChild(form);
form.submit();
}
哦,這是 jquery 版本:(代碼略有不同,但歸結為同一件事)
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
var form = $(document.createElement( "form" ))
.attr( {"method": method, "action": path} );
$.each( params, function(key,value){
$.each( value instanceof Array? value : [value], function(i,val){
$(document.createElement("input"))
.attr({ "type": "hidden", "name": key, "value": val })
.appendTo( form );
});
} );
form.appendTo( document.body ).submit();
}
如果您安裝了Prototype ,您可以收緊代碼以生成和提交隱藏表單,如下所示:
var form = new Element('form',
{method: 'post', action: 'http://example.com/'});
form.insert(new Element('input',
{name: 'q', value: 'a', type: 'hidden'}));
$(document.body).insert(form);
form.submit();
一種解決方案是生成表單並提交。 一種實現是
function post_to_url(url, params) {
var form = document.createElement('form');
form.action = url;
form.method = 'POST';
for (var i in params) {
if (params.hasOwnProperty(i)) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = i;
input.value = params[i];
form.appendChild(input);
}
}
form.submit();
}
所以我可以用一個簡單的實現一個 URL 縮短書簽
javascript:post_to_url('http://is.gd/create.php', {'URL': location.href});
好吧,希望我已經閱讀了所有其他帖子,這樣我就不會浪費時間從 Rakesh Pai 的回答中創建這個。 這是一個適用於數組和對象的遞歸解決方案。 不依賴於 jQuery。
添加了一個段來處理整個表單應該像數組一樣提交的情況。 (即,在項目列表周圍沒有包裝對象的地方)
/**
* Posts javascript data to a url using form.submit().
* Note: Handles json and arrays.
* @param {string} path - url where the data should be sent.
* @param {string} data - data as javascript object (JSON).
* @param {object} options -- optional attributes
* {
* {string} method: get/post/put/etc,
* {string} arrayName: name to post arraylike data. Only necessary when root data object is an array.
* }
* @example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
*/
function postToUrl(path, data, options) {
if (options === undefined) {
options = {};
}
var method = options.method || "post"; // Set method to post by default if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
function constructElements(item, parentString) {
for (var key in item) {
if (item.hasOwnProperty(key) && item[key] != null) {
if (Object.prototype.toString.call(item[key]) === '[object Array]') {
for (var i = 0; i < item[key].length; i++) {
constructElements(item[key][i], parentString + key + "[" + i + "].");
}
} else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
constructElements(item[key], parentString + key + ".");
} else {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", parentString + key);
hiddenField.setAttribute("value", item[key]);
form.appendChild(hiddenField);
}
}
}
}
//if the parent 'data' object is an array we need to treat it a little differently
if (Object.prototype.toString.call(data) === '[object Array]') {
if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
//loop through each array item at the parent level
for (var i = 0; i < data.length; i++) {
constructElements(data[i], (options.arrayName || "") + "[" + i + "].");
}
} else {
//otherwise treat it normally
constructElements(data, "");
}
document.body.appendChild(form);
form.submit();
};
我會像其他人建議的那樣沿着 Ajax 路線走下去:
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open("POST", "YourPageHere.asp", true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
self.xmlHttpReq.setRequestHeader("Content-length", QueryString.length);
self.xmlHttpReq.send("?YourQueryString=Value");
這里有三個選項。
標准 JavaScript 答案:使用框架! 大多數 Ajax 框架都為您提供了一種簡單的方法來制作XMLHTTPRequest POST。
自己發出 XMLHTTPRequest 請求,將 post 傳遞到 open 方法而不是 get。 ( 在 XMLHTTPRequest (Ajax)中 使用 POST 方法中的更多信息。)
通過 JavaScript,動態創建表單、添加操作、添加輸入並提交。
最簡單的方法是使用 Ajax Post Request:
$.ajax({
type: "POST",
url: 'http://www.myrestserver.com/api',
data: data,
success: success,
dataType: dataType
});
在哪里:
然后在成功處理程序中使用類似 window.location 的內容重定向瀏覽器。
這是我使用 jQuery 編寫它的方式。 在 Firefox 和 Internet Explorer 中測試。
function postToUrl(url, params, newWindow) {
var form = $('<form>');
form.attr('action', url);
form.attr('method', 'POST');
if(newWindow){ form.attr('target', '_blank');
}
var addParam = function(paramName, paramValue) {
var input = $('<input type="hidden">');
input.attr({ 'id': paramName,
'name': paramName,
'value': paramValue });
form.append(input);
};
// Params is an Array.
if(params instanceof Array){
for(var i=0; i<params.length; i++) {
addParam(i, params[i]);
}
}
// Params is an Associative array or Object.
if(params instanceof Object) {
for(var key in params){
addParam(key, params[key]);
}
}
// Submit the form, then remove it from the page
form.appendTo(document.body);
form.submit();
form.remove();
}
Prototype庫包括一個帶有“.toQueryString()”方法的 Hashtable 對象,它允許您輕松地將 JavaScript 對象/結構轉換為查詢字符串樣式的字符串。 由於帖子要求請求的“主體”是查詢字符串格式的字符串,這允許您的 Ajax 請求作為帖子正常工作。 下面是一個使用 Prototype 的例子:
$req = new Ajax.Request("http://foo.com/bar.php",{
method: 'post',
parameters: $H({
name: 'Diodeus',
question: 'JavaScript posts a request like a form request',
...
}).toQueryString();
};
這在我的情況下非常有效:
document.getElementById("form1").submit();
您可以在以下功能中使用它:
function formSubmit() {
document.getElementById("frmUserList").submit();
}
使用它,您可以發布所有輸入值。
我的解決方案將對深度嵌套的對象進行編碼,這與@RakeshPai 目前接受的解決方案不同。
它使用“qs”npm 庫及其 stringify 函數將嵌套對象轉換為參數。
此代碼適用於 Rails 后端,盡管您應該能夠通過修改傳遞給 stringify 的選項來修改它以與您需要的任何后端一起使用。 Rails 要求將 arrayFormat 設置為“括號”。
import qs from "qs"
function normalPost(url, params) {
var form = document.createElement("form");
form.setAttribute("method", "POST");
form.setAttribute("action", url);
const keyValues = qs
.stringify(params, { arrayFormat: "brackets", encode: false })
.split("&")
.map(field => field.split("="));
keyValues.forEach(field => {
var key = field[0];
var value = field[1];
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value);
form.appendChild(hiddenField);
});
document.body.appendChild(form);
form.submit();
}
例子:
normalPost("/people/new", {
people: [
{
name: "Chris",
address: "My address",
dogs: ["Jordan", "Elephant Man", "Chicken Face"],
information: { age: 10, height: "3 meters" }
},
{
name: "Andrew",
address: "Underworld",
dogs: ["Doug", "Elf", "Orange"]
},
{
name: "Julian",
address: "In a hole",
dogs: ["Please", "Help"]
}
]
});
產生這些 Rails 參數:
{"authenticity_token"=>"...",
"people"=>
[{"name"=>"Chris", "address"=>"My address", "dogs"=>["Jordan", "Elephant Man", "Chicken Face"], "information"=>{"age"=>"10", "height"=>"3 meters"}},
{"name"=>"Andrew", "address"=>"Underworld", "dogs"=>["Doug", "Elf", "Orange"]},
{"name"=>"Julian", "address"=>"In a hole", "dogs"=>["Please", "Help"]}]}
另一個遞歸解決方案,因為其他一些似乎已損壞(我沒有測試所有這些)。 這個依賴於lodash 3.x和 ES6(不需要 jQuery):
function createHiddenInput(name, value) {
let input = document.createElement('input');
input.setAttribute('type','hidden');
input.setAttribute('name',name);
input.setAttribute('value',value);
return input;
}
function appendInput(form, name, value) {
if(_.isArray(value)) {
_.each(value, (v,i) => {
appendInput(form, `${name}[${i}]`, v);
});
} else if(_.isObject(value)) {
_.forOwn(value, (v,p) => {
appendInput(form, `${name}[${p}]`, v);
});
} else {
form.appendChild(createHiddenInput(name, value));
}
}
function postToUrl(url, data) {
let form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', url);
_.forOwn(data, (value, name) => {
appendInput(form, name, value);
});
form.submit();
}
您可以使用 DHTML 動態添加表單,然后提交。
FormObject是一個選項。 但是現在大多數瀏覽器都不支持 FormObject。
您可以使用像 jQuery 這樣的庫及其$.post 方法。
這就像 Alan 的選項 2(上圖)。 如何實例化 httpobj 留作練習。
httpobj.open("POST", url, true);
httpobj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
httpobj.onreadystatechange=handler;
httpobj.send(post);
我使用 document.forms java 並循環它以獲取表單中的所有元素,然后通過 xhttp 發送。 所以這是我的javascript/ajax提交解決方案(以所有html為例):
<!DOCTYPE html>
<html>
<body>
<form>
First name: <input type="text" name="fname" value="Donald"><br>
Last name: <input type="text" name="lname" value="Duck"><br>
Addr1: <input type="text" name="add" value="123 Pond Dr"><br>
City: <input type="text" name="city" value="Duckopolis"><br>
</form>
<button onclick="smc()">Submit</button>
<script>
function smc() {
var http = new XMLHttpRequest();
var url = "yourphpfile.php";
var x = document.forms[0];
var xstr = "";
var ta ="";
var tb ="";
var i;
for (i = 0; i < x.length; i++) {
if (i==0){ta = x.elements[i].name+"="+ x.elements[i].value;}else{
tb = tb+"&"+ x.elements[i].name +"=" + x.elements[i].value;
} }
xstr = ta+tb;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
// do whatever you want to with the html output response here
}
}
http.send(xstr);
}
</script>
</body>
</html>
這是基於使用 jQuery 的 beauSD 代碼。 它得到了改進,因此它可以遞歸地處理對象。
function post(url, params, urlEncoded, newWindow) {
var form = $('<form />').hide();
form.attr('action', url)
.attr('method', 'POST')
.attr('enctype', urlEncoded ? 'application/x-www-form-urlencoded' : 'multipart/form-data');
if(newWindow) form.attr('target', '_blank');
function addParam(name, value, parent) {
var fullname = (parent.length > 0 ? (parent + '[' + name + ']') : name);
if(value instanceof Object) {
for(var i in value) {
addParam(i, value[i], fullname);
}
}
else $('<input type="hidden" />').attr({name: fullname, value: value}).appendTo(form);
};
addParam('', params, '');
$('body').append(form);
form.submit();
}
接受的答案將像本機表單提交一樣重新加載頁面。 這個修改后的版本,將通過 XHR 提交:
function post(path, params) {
const form = document.createElement('form');
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
var button = form.ownerDocument.createElement('input');
button.type = 'submit';
form.appendChild(button);
form.onsubmit = async function (e) {
console.log('hi');
e.preventDefault();
const form = e.currentTarget;
try {
const formData = new FormData(form);
const response = await fetch(path, {
method: 'POST',
body: formData,
});
console.log(response);
} catch (error) {
console.error(error);
}
};
document.body.appendChild(form);
button.click();
}
我用來發布和自動引導用戶到另一個頁面的方法是只寫一個隱藏的表單,然后自動提交它。 請放心,隱藏的表單在網頁上絕對不占空間。 代碼將是這樣的:
<form name="form1" method="post" action="somepage.php">
<input name="fielda" type="text" id="fielda" type="hidden">
<textarea name="fieldb" id="fieldb" cols="" rows="" style="display:none"></textarea>
</form>
document.getElementById('fielda').value="some text for field a";
document.getElementById('fieldb').innerHTML="some text for multiline fieldb";
form1.submit();
申請自動提交
自動提交的應用程序會將用戶自動放入另一個頁面的表單值引導回該頁面。 這樣的應用程序將是這樣的:
fieldapost=<?php echo $_post['fielda'];>
if (fieldapost !="") {
document.write("<form name='form1' method='post' action='previouspage.php'>
<input name='fielda' type='text' id='fielda' type='hidden'>
</form>");
document.getElementById('fielda').value=fieldapost;
form1.submit();
}
這是我如何做到的。
function redirectWithPost(url, data){
var form = document.createElement('form');
form.method = 'POST';
form.action = url;
for(var key in data){
var input = document.createElement('input');
input.name = key;
input.value = data[key];
input.type = 'hidden';
form.appendChild(input)
}
document.body.appendChild(form);
form.submit();
}
用於使用 POST 或 GET 重定向的 jQuery 插件:
https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
要進行測試,請包含上面的 .js 文件或將類復制/粘貼到您的代碼中,然后使用此處的代碼,將“args”替換為您的變量名稱,並將“values”替換為相應變量的值:
$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});
你可以使用jQuery的trigger方法來提交表單,就像你按下按鈕一樣,像這樣,
$('form').trigger('submit')
它將在瀏覽器上提交。
上述解決方案都沒有僅使用 jQuery 處理深層嵌套參數,所以這是我的 2 美分解決方案。
如果您使用 jQuery 並且需要處理深層嵌套參數,則可以使用下面的此函數:
/**
* Original code found here: https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
* I just simplified it for my own taste.
*/
function postForm(parameters, url) {
// generally we post the form with a blank action attribute
if ('undefined' === typeof url) {
url = '';
}
//----------------------------------------
// SOME HELPER FUNCTIONS
//----------------------------------------
var getForm = function (url, values) {
values = removeNulls(values);
var form = $('<form>')
.attr("method", 'POST')
.attr("action", url);
iterateValues(values, [], form, null);
return form;
};
var removeNulls = function (values) {
var propNames = Object.getOwnPropertyNames(values);
for (var i = 0; i < propNames.length; i++) {
var propName = propNames[i];
if (values[propName] === null || values[propName] === undefined) {
delete values[propName];
} else if (typeof values[propName] === 'object') {
values[propName] = removeNulls(values[propName]);
} else if (values[propName].length < 1) {
delete values[propName];
}
}
return values;
};
var iterateValues = function (values, parent, form, isArray) {
var i, iterateParent = [];
Object.keys(values).forEach(function (i) {
if (typeof values[i] === "object") {
iterateParent = parent.slice();
iterateParent.push(i);
iterateValues(values[i], iterateParent, form, Array.isArray(values[i]));
} else {
form.append(getInput(i, values[i], parent, isArray));
}
});
};
var getInput = function (name, value, parent, array) {
var parentString;
if (parent.length > 0) {
parentString = parent[0];
var i;
for (i = 1; i < parent.length; i += 1) {
parentString += "[" + parent[i] + "]";
}
if (array) {
name = parentString + "[" + name + "]";
} else {
name = parentString + "[" + name + "]";
}
}
return $("<input>").attr("type", "hidden")
.attr("name", name)
.attr("value", value);
};
//----------------------------------------
// NOW THE SYNOPSIS
//----------------------------------------
var generatedForm = getForm(url, parameters);
$('body').append(generatedForm);
generatedForm.submit();
generatedForm.remove();
}
這是一個如何使用它的示例。 html代碼:
<button id="testButton">Button</button>
<script>
$(document).ready(function () {
$("#testButton").click(function () {
postForm({
csrf_token: "abcd",
rows: [
{
user_id: 1,
permission_group_id: 1
},
{
user_id: 1,
permission_group_id: 2
}
],
object: {
apple: {
color: "red",
age: "23 days",
types: [
"golden",
"opal",
]
}
},
the_null: null, // this will be dropped, like non-checked checkboxes are dropped
});
});
});
</script>
如果您單擊測試按鈕,它將發布表單,您將在 POST 中獲得以下值:
array(3) {
["csrf_token"] => string(4) "abcd"
["rows"] => array(2) {
[0] => array(2) {
["user_id"] => string(1) "1"
["permission_group_id"] => string(1) "1"
}
[1] => array(2) {
["user_id"] => string(1) "1"
["permission_group_id"] => string(1) "2"
}
}
["object"] => array(1) {
["apple"] => array(3) {
["color"] => string(3) "red"
["age"] => string(7) "23 days"
["types"] => array(2) {
[0] => string(6) "golden"
[1] => string(4) "opal"
}
}
}
}
注意:如果要將表單發布到當前頁面以外的其他 url,可以將 url 指定為 postForm 函數的第二個參數。
例如(重新使用您的示例):
postForm({'q':'a'}, 'http://example.com/');
希望這可以幫助。
注2:代碼取自重定向插件。 我基本上只是根據我的需要簡化了它。
嘗試
function post_to_url(url, obj) { let id=`form_${+new Date()}`; document.body.innerHTML+=` <form id="${id}" action="${url}" method="POST"> ${Object.keys(obj).map(k=>` <input type="hidden" name="${k}" value="${obj[k]}"> `)} </form>` this[id].submit(); } // TEST - in second param object can have more keys function jump() { post_to_url('https://example.com/', {'q':'a'}); }
Open chrome>networks and push button: <button onclick="jump()">Send POST</button>
您可以進行AJAX調用(可能使用諸如使用Prototype.js或JQuery之類的庫)。 AJAX可以處理GET和POST選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.