Եվ նվազագույն օգնությունը կլինի ձեր մշակած գործառույթից: PHP: \"Մեջբերումներ\": Mysql հարցումներ գրել, կտրատել, չակերտներից խուսափել Որոնում կոդով
չակերտների տող (11)
Ես փորձում եմ գտնել հարցումներ գրելու լավագույն միջոցը: Ես նաև հասկանում եմ հետևողական լինելու կարևորությունը։ Առայժմ ես պատահականորեն օգտագործում էի միայնակ չակերտներ, կրկնակի չակերտներ և հետնահերթներ՝ առանց իրական մտածելու:
$query = «INSERT INTO աղյուսակի (id, col1, col2) VALUES (NULL, val1, val2)»;
Բացի այդ, վերը նշված օրինակում հաշվի առեք, որ «աղյուսակը», «col[n]» և «val[n]» կարող են լինել փոփոխականներ:
Ո՞րն է դրա չափանիշը: Ինչ ես անում?
Մոտ 20 րոպե ես կարդում եմ նմանատիպ հարցերի պատասխանները, բայց այս հարցին վերջնական պատասխան կարծես թե չկա:
Պատասխանները
Հիմա ենթադրենք, որ MySQL հարցումում օգտագործում եք ուղղակի գրառման փոփոխական, ապա օգտագործեք այն այսպես.
$query = "INSERT INTO `աղյուսակ` (`id`, `name`, `email`) VALUES (" ".$_POST["id"]." ", " ".$_POST["name"]." ", " ".$_POST["email"].." ")";
Սա MySQL-ում PHP փոփոխականների օգտագործման լավագույն պրակտիկան է:
Հիմնականում Mysql-ում այս տեսակի նույնացուցիչներն օգտագործվում են ` , " , " և () հարցումներում։
" կամ " օգտագործել տողը որպես արժեք ներառելու համար "01/26/2014 00:00:00" կամ "01/26/2014 00:00:00" . Այս նույնացուցիչն օգտագործվում է միայն «01/26/2014 00:00:00» տողային ֆունկցիայի համար, օրինակ՝ now() կամ sum ,max.
Օգտագործեք աղյուսակ կամ աղյուսակ աղյուսակ ներառելու համար, օրինակ՝ աղյուսակի անունից ընտրեք սյունակի_անունը, որտեղ id = "2"
() օգտագործվում են միայն հարցման մասերը պարզապես կցելու համար, օրինակ՝ ընտրեք սյունակի_անունը table_name-ից, որտեղ (id = «2» և սեռը = «տղամարդ») կամ անունը = «rakesh»:
Բացի բոլոր (լավ բացատրված) պատասխաններից, ստորև նշված չկար, և ես հաճախ եմ գալիս այս հարցուպատասխանին:
Մի խոսքով; MySQL-ը կարծում է, որ դուք ցանկանում եք մաթեմատիկա անելձեր սեփական սեղանի/սյունակի վրա և մեկնաբանեք գծիկները, ինչպիսիք են «էլ. փոստը» որպես էլ. փոստ:
Պատասխանատվության մերժում.Այսպիսով, ես մտածեցի, որ սա կավելացնեմ որպես «FYI» պատասխան նրանց համար, ովքեր լիովին նոր են աշխատել տվյալների բազաների հետ, և ովքեր կարող են չհասկանալ արդեն նկարագրված տեխնիկական տերմինները:
(Վերևում կան լավ պատասխաններ ձեր հարցի SQL բնույթի վերաբերյալ, բայց դա կարող է նաև համապատասխան լինել, եթե դուք նոր եք PHP-ում:)
Կարևոր է նշել, որ PHP-ն տարբեր կերպ է վերաբերվում մեկ և կրկնակի մեջբերումներին...
Մեկ մեջբերումով տողերը «բառացի» են և բավականին շատ WYSIWYG տողեր են: Կրկնակի մեջբերված տողերը մեկնաբանվում են PHP-ի կողմից՝ հնարավոր փոփոխականների փոխարինման համար (PHP-ի հետադարձ հղումները հենց տողեր չեն, դրանք կատարում են հրամանը shell-ում և վերադարձնում արդյունքը):
$foo = «բար»; echo «կա $foo»; // Կա $foo echo «կա $foo»; // Կա բար echo `ls -l`; // ... գրացուցակի ցուցակ
Եթե cols աղյուսակները և արժեքները փոփոխական են, ապա կա երկու եղանակ.
Կրկնակի չակերտներով «» ամբողջական հարցումը հետևյալն է.
$query = "INSERT INTO $table_name (id, $col1, $col2) VALUES (NULL, "$val1", "$val2")";
$query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.") VALUES (NULL, "".$val1.", "".$val2."" ) «;
Մեկ չակերտներով «» :
$query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.") VALUES (NULL, ".$val1.", ".$val2.")";
Օգտագործեք հետնահերթներ ``, երբ սյունակի/արժեքի անունը նման է MySQL վերապահված հիմնաբառին:
Նշում.Եթե դուք նշում եք սյունակի անվանումը աղյուսակի անունով, օգտագործեք հետևյալ ետադարձները.
«աղյուսակի_անունը»: «սյունակի_անունը»:<- Примечание: исключить. из задних клещей.
Backtick-երը պետք է օգտագործվեն աղյուսակների և սյունակների նույնացուցիչների համար, սակայն անհրաժեշտ են միայն այն դեպքում, երբ նույնացուցիչը MySQL-ի վերապահված հիմնաբառ է կամ երբ նույնացուցիչը պարունակում է բացատ կամ նիշեր սահմանափակ հավաքածուից դուրս (տես ստորև): Հաճախ խորհուրդ է տրվում խուսափել վերապահված հիմնաբառեր որպես սյունակի կամ աղյուսակի նույնացուցիչներ օգտագործելուց՝ հնարավորության դեպքում՝ չակերտների խնդրից խուսափելու համար:
Միայնակ չակերտները պետք է օգտագործվեն տողային արժեքների համար, օրինակ՝ VALUES() ցանկում: Կրկնակի չակերտները աջակցվում են MySQL-ի կողմից նաև լարային արժեքների համար, սակայն առանձին չակերտներն ավելի լայնորեն ընդունված են այլ RDBMS-ների կողմից, ուստի լավ գաղափար է կրկնակի չակերտների փոխարեն օգտագործել միայնակ չակերտներ:
MySQL-ը նաև ակնկալում է, որ DATE և DATETIME բառացի արժեքները միանվագ մեջբերվեն որպես տողեր, օրինակ՝ «2001-01-01 00:00:00»: Լրացուցիչ տեղեկությունների համար տե՛ս Ամսաթվի և ժամի գրականության փաստաթղթերը, մասնավորապես գծիկն օգտագործելու այլընտրանքները՝ որպես տարանջատող տարանջատիչ ամսաթվի տողերում:
Այսպիսով, օգտագործելով ձեր օրինակը, ես կկրկնապատկեի PHP տողը և կօգտագործեի միայնակ չակերտներ «val1», «val2» արժեքների համար: NULL-ը MySQL հիմնաբառ է և ոչ արժեք և, հետևաբար, չի օգտագործվում:
Այս աղյուսակի կամ սյունակի նույնացուցիչներից և ոչ մեկը վերապահված բառեր չեն կամ օգտագործում են նիշեր, որոնք պահանջում են մեջբերումներ, բայց ես, այնուամենայնիվ, դրանք մեջբերել եմ հետընթացով (այդ մասին ավելի ուշ...):
RDBMS-ի հետ կապված գործառույթները (օրինակ՝ NOW() MySQL-ում) չպետք է մեջբերվեն, թեև դրանց արգումենտները ենթակա են նույն կանոններին կամ մեջբերումների կանոններին, որոնք արդեն նշված են։
Backtick(`) աղյուսակ և սյունակ ┬──── ┬──┬───────┐ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ՏԵՂԱԴՐԵԼ «աղյուսակի» մեջ («id», «col1», «col2», «ամսաթիվ», «թարմացված») ԱՐԺԵՔՆԵՐ (NULL, «val1», «val2», «2001-01-01», NOW())«; Չակերտավոր հիմնաբառ ─────┴┴┴┘ │ │ │ │ │ │ │││││ │││││ │││││ Մեկ մեջբերումով (") տողեր ─││ ─ ───┴── ┴────┘ │ │ │││││ Մեկ մեջբերում (") DATE ───── ─ ───┴── Չակերտավոր գործառույթ ────────────────────────── ─────── ──┴┴┴┴┘
Փոփոխական ինտերպոլացիա
Փոփոխականների համար մեջբերումների օրինաչափությունները չեն փոխվում, չնայած եթե դուք մտադիր եք փոփոխականները ներդնել ուղղակի տողի մեջ, այն պետք է կրկնակի մեջբերվի PHP-ում: Պարզապես համոզվեք, որ դուք պատշաճ կերպով փախել եք փոփոխականներից SQL-ում օգտագործելու համար: (Խորհուրդ է տրվում օգտագործել API, որն աջակցում է պատրաստված հայտարարություններին՝ որպես պաշտպանություն SQL ներարկումից:)
// Նույնը որոշ փոփոխականների փոխարինման դեպքում // Այստեղ փոփոխական աղյուսակի անունը $table նշված է հետադարձ մեջբերումով, և // փոփոխականները VALUES ցուցակում մեկ մեջբերում են $query = "INSERT INTO «$սեղան».(«id», «col1», «col2», «date») VALUES (NULL, «$val1», «$val2», «$ամսաթիվ»)";
Պատրաստված հայտարարություններ
Պատրաստված քաղվածքների հետ աշխատելիս խորհրդակցեք փաստաթղթերի հետ՝ որոշելու համար, թե արդյոք պետք է ներառվեն քաղվածքները լրացնող նյութերը: Ամենատարածված API-ները, որոնք հասանելի են PHP-ում, PDO-ում և MySQLi-ում, ներառում են չարտոնվածտեղապահներ, ինչպես այլ լեզուներով պատրաստված հրահանգների API-ների մեծ մասը.
// PDO օրինակ՝ անվանված պարամետրերով, չակերտավոր $query = "INSERT INTO `աղյուսակում` (`id`, `col1`, `col2`, "date`) VALUES (:id, :col1, :col2, :date)" ; // MySQLi օրինակ ? պարամետրեր, unquoted $query = "INSERT INTO `աղյուսակ` (`id`, `col1`, `col2`, `date`) VALUES (?, ?, ?, ?)";
Նշաններ, որոնք վերադարձնում են հետադարձ հղում նույնացուցիչներում.
Օրինակ:
Նույնը կարելի է անել աղյուսակների և դաշտերի անունների համար: Սա շատ լավ սովորությունեթե ձեր տվյալների բազան կապում եք հետևի պատուհանների հետ:
Ստուգեք այս պատասխանը՝ հակադարձ եզրակացությունների մասին ավելին իմանալու համար:
Հիմա կրկնակի մեջբերումների և միայնակ մեջբերումների մասին (Մայքլն արդեն նշել է սա):
Բայց արժեքը սահմանելու համար հարկավոր է օգտագործել մեկ կամ կրկնակի չակերտներ: Տեսնենք մեկ այլ օրինակ.
INSERT INTO «աղյուսակի անունը» («id, «title») ԱՐԺԵՔՆԵՐԸ (NULL, title1);
Այստեղ ես միտումնավոր մոռացել էի վերնագիրը չակերտներով փաթաթել։ Այժմ սերվերը կընդունի title1-ը որպես սյունակի անուն (այսինքն՝ նույնացուցիչ): Այսպիսով, նշելու համար, որ սա արժեք է, դուք պետք է օգտագործեք կրկնակի կամ մեկ չակերտներ:
INSERT INTO «աղյուսակի անունը» («id, «title») VALUES (NULL, «title1»);
Այժմ, PHP-ի հետ զուգակցված, կրկնակի չակերտները և մեկ չակերտները շատ ավելի հեշտ են դարձնում հարցումների գրելը: Եկեք նայենք ձեր հարցի փոփոխված տարբերակին:
$query = "INSERT INTO `աղյուսակում" (`id`, `col1`, `col2`) ԱՐԺԵՔՆԵՐ (NULL, "$val1", "$val2"");
Այժմ, օգտագործելով կրկնակի չակերտներ PHP-ում, դուք կստիպեք $val1 և $val2 փոփոխականներն օգտագործել իրենց արժեքները՝ այդպիսով ստեղծելով վավեր հարցում։ նման
$val1 = «իմ արժեքը 1»; $val2 = «իմ արժեքը 2»; $query = "INSERT INTO `աղյուսակում" (`id`, `col1`, `col2`) ԱՐԺԵՔՆԵՐ (NULL, "$val1", "$val2"");
ՄՏԱՑՐԵԼ «աղյուսակի» մեջ («id», «col1», «col2») ԱՐԺԵՔՆԵՐԸ (NULL, «իմ արժեքը 1», «իմ արժեքը 2»)
Այստեղ կային շատ օգտակար պատասխաններ, որոնք ընդհանուր առմամբ ավարտվում էին երկու կետով:
- BACKTICKS (`) օգտագործվում են նույնացուցիչների անունների շուրջ:
- ՄԵԿ ՄԵՋԱԿՏԵՐ (") օգտագործվում են արժեքների շուրջ:
Եվ ինչպես @MichaelBerkowski-ն ասաց
Backtick-երը պետք է օգտագործվեն աղյուսակների և սյունակների նույնացուցիչների համար, սակայն անհրաժեշտ են միայն այն դեպքում, երբ նույնացուցիչը MySQL-ի վերապահված հիմնաբառ է կամ երբ նույնացուցիչը պարունակում է բացատ կամ նիշեր սահմանափակ հավաքածուից դուրս (տես ստորև): Հաճախ խորհուրդ է տրվում խուսափել վերապահված հիմնաբառեր որպես սյունակի կամ աղյուսակի նույնացուցիչներ օգտագործելուց՝ հնարավորության դեպքում՝ չակերտների խնդրից խուսափելու համար:
Կա դեպք, երբ նույնացուցիչը չի կարող լինել վերապահված հիմնաբառկամ պարունակում է բացատ նիշերկամ նիշերը սահմանափակ հավաքածուից դուրսբայց անպայման պահանջում են հետհղումներ դրանց շուրջ:
123E10-ը վավեր նույնացուցիչ անուն է, բայց նաև վավեր INTEGER բառացի:
[Առանց մանրամասնելու, թե ինչպես դուք կստանաք նման id անուն] Ենթադրենք, ես ուզում եմ ստեղծել ժամանակավոր աղյուսակ, որը կոչվում է 123456e6:
Չկա ՍԽԱԼ հետքայլերի վրա:
DB > ստեղծել ժամանակավոր աղյուսակ `123456e6` (`id` char (8)); Հարցումը լավ է, 0 տող է ազդել (0,03 վրկ)
ՍԽԱԼ, եթե չեք օգտագործում հետզանգեր:
DB > ստեղծել ժամանակավոր աղյուսակ 123451e6 (`id` char (8)); ՍԽԱԼ 1064 (42000). Ձեր SQL շարահյուսության մեջ սխալ կա. ստուգեք ձեռնարկը, որը համապատասխանում է ձեր MariaDB սերվերի տարբերակին, որպեսզի ճիշտ շարահյուսություն օգտագործվի «123451e6 (`id` char (8))» մոտ 1-ին տողում:
Այնուամենայնիվ, 123451a6-ը լավ նույնականացման անուն է (առանց հետքերով):
DB > ստեղծել ժամանակավոր աղյուսակ 123451a6 (`id` char (8)); Հարցումը լավ է, 0 տող է ազդել (0,03 վրկ)
Սա ամբողջությամբ պայմանավորված է նրանով, որ 1234156e6-ը նույնպես էքսպոնենցիալ թիվ է:
Միայնակ չակերտները պետք է օգտագործվեն տողային արժեքների համար, օրինակ՝ VALUES() ցանկում:
Backtick-ները սովորաբար օգտագործվում են նույնացուցիչը նշելու համար և կարող են նաև ապահով լինել վերապահված հիմնաբառերի երբեմն օգտագործման պատճառով:
Երբ զուգակցվում են PHP-ի և MySQL-ի հետ, կրկնակի չակերտները և մեկ մեջբերումները մեծապես պարզեցնում են հարցումների գրման ժամանակը:
MySQL-ում գնանշումների երկու տեսակ կա.
- « ներառել լարային բառացիները
- ` ներառել նույնացուցիչներ, ինչպիսիք են աղյուսակների և սյունակների անունները
Եվ հետո կա «սա հատուկ դեպք է, այն կարող է օգտագործվել մեկվերը նշված թիրախներից միաժամանակ՝ կախված սերվերի sql_mode-ից.
- Կանխադրված«նիշը» կարող է օգտագործվել լարային տառերի բույն դնելու համար»
- ANSI_QUOTES ռեժիմում « խորհրդանիշը կարող է օգտագործվել նույնացուցիչներ ներառելու համար, ANSI_QUOTES
Հետևյալ հարցումը կհանգեցնի տարբեր արդյունքների (կամ սխալների)՝ կախված SQL ռեժիմից.
Ընտրեք «սյունակ» աղյուսակից WHERE foo = «բար»ANSI_QUOTES անջատված է
Հարցումը կընտրի տողի բառացի «սյունակը», որտեղ foo սյունակը հավասար է «բար» տողի
Միացված է ANSI_QUOTES
Հարցումը կընտրի սյունակի սյունակը, որտեղ foo սյունակը հավասար է սյունակի
Երբ օգտագործել
- Առաջարկում եմ խուսափել «»-ի օգտագործումից, որպեսզի ձեր կոդը կախված չլինի SQL ռեժիմներից
- Միշտ ներառեք նույնացուցիչներ, քանի որ սա լավ պրակտիկա է (SO-ի վերաբերյալ բավականին մի քանի հարցեր քննարկում են սա)
Հստակ տարբերություն կա " "-ի և " "-ի օգտագործման միջև:
Երբ « «»-ն օգտագործվում է ամբողջ ընթացքում, «փոխակերպում կամ թարգմանություն» չկա: Տպագրված է այնպես, ինչպես կա։
« »-ի հետ այն, ինչ շրջապատում է, «թարգմանվում կամ փոխակերպվում է» իր արժեքի։
Թարգմանություն/փոխակերպում ասելով ես նկատի ունեմ հետևյալը. միայնակ չակերտներում պարունակվող ցանկացած բան չի «թարգմանվի» իրենց արժեքներին: Նրանք կընդունվեն, քանի որ դրանք ներսում են չակերտների մեջ: Օրինակ՝ a=23, այնուհետև «$a»-ի արձագանքը կստեղծի $a ստանդարտ ելքի վրա: Մինչդեռ echo «$a»-ն կարտադրի 23 ստանդարտ ելքի վրա:
(PHP 4 >= 4.3.0, PHP 5)
mysql_real_escape_string — Խուսափում է տողի հատուկ նիշերից SQL հայտարարությունում օգտագործելու համար
Նկարագրություն
mysql_real_escape_string (տող $unescaped_string [, ռեսուրս $link_identifier = NULL]): լար
Խուսափում է հատուկ նիշերից unescaped_string-ում, հաշվի առնելով կապի ներկայիս նիշերի հավաքածուն, որպեսզի այն անվտանգ տեղադրվի mysql_query (). Եթե պետք է տեղադրվեն երկուական տվյալներ, ապա այս գործառույթը պետք է օգտագործվի:
mysql_real_escape_string() կանչում է MySQL-ի գրադարանային ֆունկցիան mysql_real_escape_string, որը հետևում է հետևյալ նիշերին. \x00, \n, \ր, \ , " , " և \x1a.
Այս ֆունկցիան միշտ (մի քանի բացառություններով) պետք է օգտագործվի տվյալների անվտանգությունն ապահովելու համար՝ նախքան հարցում ուղարկելը MySQL:
Զգուշություն
Անվտանգություն. լռելյայն նիշերի հավաքածու
Նիշերի հավաքածուն պետք է սահմանվի կամ սերվերի մակարդակում, կամ API ֆունկցիայի հետ mysql_set_charset ()որպեսզի այն ազդի mysql_real_escape_string() . Լրացուցիչ տեղեկությունների համար տե՛ս նիշերի հավաքածուների հասկացությունների բաժինը:
Պարամետրեր
unescaped_string
Շարանը, որից պետք է փախչել։
Link_identifier
MySQL կապը. Եթե հղման նույնացուցիչը նշված չէ, վերջին հղումը բացվել է mysql_connect ()ենթադրվում է. Եթե նման հղում չգտնվի, այն կփորձի ստեղծել, կարծես mysql_connect ()կանչվել էր առանց փաստարկների։ Եթե որևէ կապ չի գտնվել կամ հաստատվել, ա E_ԶԳՈՒՇԱՑՈՒՄմակարդակի սխալ է առաջանում:
Վերադարձի արժեքներ
Վերադարձնում է փախած տողը կամ ՍՈՒՏսխալի վրա։
Սխալներ/Բացառություններ
Այս ֆունկցիան առանց MySQL կապի գործարկելը նույնպես կթողարկվի E_ԶԳՈՒՇԱՑՈՒՄմակարդակի PHP սխալներ. Կատարեք այս գործառույթը միայն վավեր MySQL կապի առկայության դեպքում:
Օրինակներ
Օրինակ #1 Պարզ mysql_real_escape_string() օրինակ
//Միացնել
$link = mysql_connect("mysql_host" , "mysql_user" , "mysql_password")
ԿԱՄ die (mysql_error ());
//Հարցում
$query = sprintf ( «Ընտրեք * Օգտատերերից ՈՐՏԵՂ օգտվող ===«%s» ԵՎ գաղտնաբառ==%s»»,
mysql_real_escape_string ($user),
mysql_real_escape_string ($գաղտնաբառ));
?>
Օրինակ #2 mysql_real_escape_string() պահանջում է կապի օրինակ
Այս օրինակը ցույց է տալիս, թե ինչ է տեղի ունենում, եթե այս ֆունկցիան կանչելիս չկա MySQL կապ:
Վերոնշյալ օրինակը կարտադրի նման բան.
Զգուշացում՝ mysql_real_escape_string(): Նման ֆայլ կամ գրացուցակ չկա /this/test/script.php-ում 5-րդ տողում Զգուշացում. mysql_real_escape_string(). bool(false) string(41) "SELECT * FROM actors WHERE last_name = """
Օրինակ #3 SQL Injection Attack-ի օրինակ
// Մենք չենք ստուգել $_POST["password"], դա կարող է լինել այն ամենը, ինչ օգտատերը ցանկանում է: Օրինակ.
$_POST [ "username" ] = "aidan" ;
$_POST [ "password" ] = "" OR ""="" ;
// Հարցման տվյալների բազան ստուգելու համար, թե արդյոք կան համապատասխան օգտվողներ
$query = ( $_POST [ "username" ]) "AND password=" ($_POST ["password"]) "" ;
mysql_query ($ հարցում);
// Սա նշանակում է, որ MySQL-ին ուղարկված հարցումը կլինի.
արձագանք $ հարցում ;
?>
MySQL-ին ուղարկված հարցումը՝
Սա թույլ կտա բոլորին մուտք գործել առանց վավեր գաղտնաբառի:
Նշումներ
Օգտագործելուց առաջ անհրաժեշտ է MySQL կապ mysql_real_escape_string() հակառակ դեպքում մակարդակի սխալ E_ԶԳՈՒՇԱՑՈՒՄառաջանում է, և ՍՈՒՏվերադարձվում է։ Եթե link_identifier-ը սահմանված չէ, ապա օգտագործվում է վերջին MySQL կապը:
Նշում: mysql_real_escape_string() չի փախչում % և _ . Դրանք MySQL-ի նիշերն են, եթե համակցված են Հավանել, ԳՐԱՆՏ, կամ ՈՒՂԻՂ.
8 տարի առաջ
Պարզապես մի փոքրիկ ֆունկցիա, որը նմանակում է բնօրինակ mysql_real_escape_string-ին, բայց որն ակտիվ mysql կապի կարիք չունի: Կարող է իրականացվել որպես ստատիկ ֆունկցիա տվյալների բազայի դասում: Հուսով եմ, որ դա կօգնի ինչ-որ մեկին:
ֆունկցիա mysql_escape_mimic ($inp) (
if (is_array ($inp))
վերադարձնել array_map (__METHOD__, $inp);
Եթե (! դատարկ ($inp ) && is_string ($inp )) (
return str_replace (array("\\" , "\0", "\n", "\r", """, """ , "\x1a" ), array("\\\\" , "\ \0" , "\\n", "\\r", "\\"", "\\"", "\\Z"), $inp);
}
Վերադարձ $inp ;
}
?>
13 տարի առաջ
Նկատի ունեցեք, որ mysql_real_escape_string-ը չի կապում \x00, \n, \r և \x1a հետադարձ կտրվածքները, ինչպես նշված է փաստաթղթերում, բայց իրականում նիշը փոխարինում է հարցումների համար MySQL ընդունելի ներկայացմամբ (օրինակ, \n-ը փոխարինվում է "\-ով: n" բառացի): (\, ", և "-ը փաստաթղթավորված են) Սա չի փոխում, թե ինչպես պետք է օգտագործել այս գործառույթը, բայց կարծում եմ, որ լավ է իմանալ:
6 տարի առաջ
Փախուստի մասին ոչ մի քննարկում ավարտված չէ առանց բոլորին ասելու, որ հիմնականում երբեք չպետք է օգտագործեք արտաքին մուտքագրում՝ մեկնաբանված կոդ ստեղծելու համար: Սա վերաբերում է SQL հայտարարություններին կամ որևէ այլ բանի, որը դուք կարող եք անվանել ցանկացած «eval» ֆունկցիա:
Այսպիսով, այս սարսափելի կոտրված ֆունկցիան օգտագործելու փոխարեն, դրա փոխարեն օգտագործեք պարամետրային պատրաստված հայտարարություններ:
Անկեղծ ասած, SQL հայտարարություններ կազմելու համար օգտագործողի կողմից տրամադրված տվյալների օգտագործումը պետք է համարվի մասնագիտական անփութություն, և դուք պետք է պատասխանատվություն կրեք ձեր գործատուի կամ հաճախորդի կողմից՝ պարամետրային պատրաստված հայտարարություններ չօգտագործելու համար:
Ինչ է դա նշանակում?
Դա նշանակում է SQL հայտարարություն կառուցելու փոխարեն այսպես.
"INSERT INTO X (A) VALUES(".$_POST["a"].")"
Դուք պետք է օգտագործեք mysqli's prepare() ֆունկցիան ()՝ այսպիսի հայտարարություն կատարելու համար.
«INSERT INTO X (A) VALUES(?)»
Նշում. Սա չի նշանակում, որ դուք երբեք չպետք է գեներացնեք դինամիկ SQL հայտարարություններ: Դա նշանակում է, որ դուք երբեք չպետք է օգտագործեք օգտվողի կողմից տրամադրված տվյալներ այդ հայտարարությունները ստեղծելու համար: Օգտատիրոջ կողմից տրամադրված ցանկացած տվյալ պետք է փոխանցվի որպես պարամետր հայտարարության մեջ այն ստանալուց հետո: պատրաստվել է.
Այսպիսով, օրինակ, եթե դուք ստեղծում եք մի փոքր շրջանակ և ցանկանում եք աղյուսակում ներդիր անել՝ հիմնվելով հարցման URI-ի վրա, ձեր լավագույն շահերից է բխում, որ չվերցնեք $_SERVER["REQUEST_URI"] արժեքը (կամ որևէ մեկը: դրա մի մասը) և ուղղակիորեն միացրեք այն ձեր հարցմանը: Փոխարենը, դուք պետք է վերլուծեք $_SERVER["REQUEST_URI"] արժեքի այն մասը, որը ցանկանում եք, և այն քարտեզագրեք ինչ-որ ֆունկցիայի կամ ասոցիատիվ զանգվածի միջոցով ոչ օգտատիրոջը: տրամադրված արժեք Եթե քարտեզագրումը արժեք չի տալիս, դուք գիտեք, որ ինչ-որ բան այն չէ, ինչ-որ բան սխալ է օգտատիրոջ տրամադրած տվյալների հետ:
Սրան չհետևելը մի շարք SQL-ներարկման խնդիրների պատճառ է դարձել Ruby On Rails-ի շրջանակում, թեև այն օգտագործում է պարամետրային պատրաստված հայտարարություններ: Ահա թե ինչպես են կոտրել GitHub-ը մի պահ. Այսպիսով, ոչ մի լեզու պաշտպանված չէ այս խնդրից: Ահա թե ինչու սա ընդհանուր լավագույն պրակտիկա է և ոչ թե հատուկ PHP-ին, և ինչու պետք է ԻՐՈՔ ընդունեք այն:
Բացի այդ, դուք դեռ պետք է կատարեք օգտատերերի կողմից տրամադրված տվյալների որոշակի վավերացում, նույնիսկ երբ օգտագործում եք պարամետրային պատրաստված հայտարարություններ: Դա պայմանավորված է նրանով, որ օգտագործողի կողմից տրամադրված այդ տվյալները հաճախ դառնում են որոշ ստեղծած HTML-ի մաս, և դուք ցանկանում եք համոզվել, որ օգտատիրոջ տրամադրած տվյալները զննարկիչում անվտանգության հետ կապված խնդիրներ չեն առաջացնի:
9 տարի առաջ
Օրինակ 2-ում SQL ներարկման հետ կապված հետաքրքիր տարօրինակություն կա. AND-ը առաջնահերթություն է ստանում OR-ից, ուստի ներարկված հարցումն իրականում կատարվում է որպես WHERE (user="aidan" AND password="") OR ""="", ուստի փոխարենը կամայական օգտանունին համապատասխանող տվյալների բազայի գրառումը վերադարձնելու դեպքում (այս դեպքում՝ «aidan»), այն իրականում կվերադարձնի տվյալների շտեմարանի ԲՈԼՈՐ գրառումները: Առանց հատուկ հերթականության: Այսպիսով, հարձակվողը կարող է մուտք գործել որպես ցանկացած հաշիվ, բայց ոչ պարտադիր: վերահսկել, թե որ հաշիվն է դա:
Իհարկե, հարձակման պոտենցիալը կարող է պարզապես փոփոխել իրենց պարամետրերը` թիրախավորելու հատուկ հետաքրքրություն ունեցող օգտվողներին.
//Օրինակ. հարձակվողի արժեքները
$_POST [ "username" ] = "" ;
$_POST [«գաղտնաբառ»] = "" ԿԱՄ օգտվող = "ադմինիստրատոր" ԵՎ "" = "";
// Սխալ ձևավորված հարցում
$ հարցում = "SELECT * FROM users WHERE user="$_POST [ username ] " AND password = " $_POST [գաղտնաբառ ] "" ;
արձագանք $ հարցում ;
// MySQL-ին ուղարկված հարցումը կարդա.
// SELECT * FROM users WHERE user="" AND password="" OR user="administrator" AND ""="";
// որը թույլ կտա յուրաքանչյուրին մուտք ունենալ «ադմինիստրատոր» անունով հաշիվ
?>
1 տարի առաջ
@feedr
Ես նրա գրառումը բացատրեցի հետևյալ կերպ.
$string = "asda\0sd\x1aas\\\\\\\\dasd \"asdasd\na\"\"sdasdad";
$array1 = զանգված ("\\\\\\\\", "\0", "\n", "\r", """, """, "\x1a");
$array2 = զանգված ("\\\\\\\\\\\\\\\\\", "\\\0", "\\\n", "\\\r", "\\\ " ", "\\\"", "\\\Z");
echo ($string);
echo (PHP_EOL);
համար ($i=0; $i
$p = «/(?ուրիշ
$p = «/(?արձագանք ($i);
echo ($ p);
echo ($array2[$i]);
$string = preg_replace ($p, $array2[$i], $string);
echo ("\t");
echo ($string);
echo (PHP_EOL);
}
echo (PHP_EOL);
echo ($string);
2 տարի առաջ
Սեմին մեջբերել Numb Safari-ում
[ «Փախուստի մասին ոչ մի քննարկում ավարտված չէ առանց բոլորին ասելու, որ հիմնականում երբեք չպետք է օգտագործեք արտաքին մուտքագրում՝ մեկնաբանված կոդ ստեղծելու համար: Սա վերաբերում է SQL հայտարարություններին, կամ ցանկացած այլ բանի, որի վրա կարող եք անվանել «eval» ֆունկցիա:
Այսպիսով, այս սարսափելի կոտրված ֆունկցիան օգտագործելու փոխարեն, դրա փոխարեն օգտագործեք պարամետրային պատրաստված հայտարարություններ:
Անկեղծ ասած, SQL հայտարարություններ կազմելու համար օգտագործողի կողմից տրամադրված տվյալների օգտագործումը պետք է համարվի մասնագիտական անփութություն, և դուք պետք է պատասխանատվություն կրեք ձեր գործատուի կամ հաճախորդի կողմից՝ պարամետրային պատրաստված հայտարարություններ չօգտագործելու համար»: ]
Սեմը ճիշտ է ասում......
Այնուամենայնիվ, խելամիտ չեմ համարում դադարեցնել բոլոր ախտահանումները և ուղղակի առաջադրանքը հանձնել պարամետրային պատրաստված հայտարարություններին։
Կոնկրետ իրավիճակում աշխատող կոնկրետ մշակողը միշտ ավելին կիմանա վավեր մուտքագրման մասին (հատուկ այդ համատեքստում):
Եթե օգտագործողից խնդրեք փոխանցել մի արժեք, որը դուք արդեն տվել եք նրան, և դուք գիտեք, որ բոլոր այդպիսի արժեքները սկսվում են AB****** և տողը պետք է լինի 7 կամ 11 երկարության, բայց ոչ մի այլ երկարության, ապա դուք ունեք լավ նախնական ախտահանիչի հիմքը. տողի տարբեր թույլատրելի երկարությունները կարող են ցույց տալ ժառանգական տվյալներ:
Ես երբեք չեմ ցանկանա ուղղակի աղբը, որը չարամիտ օգտվողը կարող է փոխանցել ձևի միջոցով, փոխանցել պարամետրային պատրաստված հայտարարություններին, ես միշտ կցանկանայի առաջին հերթին կատարել իմ առողջական վիճակի ստուգումները, և որոշ դեպքերում դրանք կարող են զգույշ լինել: պարզապես ընտրեք ամբողջությամբ դադարեցնել տվյալների բազայի գործողությունը:
Այդ կերպ իմ DB-ն չի խցանվում անվտանգ հայտարարություններով. այն պարզապես չի խցանվում, որն ավելի լավ է:
Անվտանգությունը շերտերում. ախտահանումը և վավերացումը դեռևս պետք է դիտարկվեն յուրաքանչյուր իրավիճակում ԱՌԱՆՑ պատրաստված հայտարարությունները օգտագործելուց:
Բացի այդ, որքանով ես կարող եմ կարդալ պաշտոնական փաստաթուղթը
==============================================
«Փախուստ և SQL ներարկում
Կապված փոփոխականները սերվերին ուղարկվում են հարցումից առանձին և այդպիսով չեն կարող խանգարել դրան: Սերվերն օգտագործում է այս արժեքները անմիջապես կատարման կետում՝ քաղվածքի ձևանմուշը վերլուծելուց հետո: Կապված պարամետրերը պետք չէ փախչել, քանի որ դրանք երբեք ուղղակիորեն չեն փոխարինվում հարցման տողի մեջ»:
Դա ինձ հուշում է, որ վտանգը ներքուստ խուսափում է այլընտրանքային վարվելակերպով, ոչ թե զրոյացումով:
Սա նշանակում է, որ մեծ նախագիծը, որը թերի փոխակերպվում է պատրաստված հայտարարություններին, կազմակերպության տարբեր մասերում կամ միմյանց հետ խոսող սերվերների ժառանգական ծածկագիրը կարող է վատ լուրը փոխանցել անձեռնմխելի վայրից կամ իրավիճակից դեպի մեկը, որն անձեռնմխելի է:
Քանի դեռ ախտահանումը կատարվում է գրագետ, առանց հավելյալ ռիսկեր կրելու, ապա անձամբ ես կպահպանեմ սանմաքրման որոշակի շերտեր, ապա կկանչեմ պատրաստված հայտարարությունները:
Նախ, մի փոքր այն մասին, թե ինչու են ընդհանուր առմամբ անհրաժեշտ այս կտրվածքները:
Եթե որևէ տվյալ փոխարինենք հարցման մեջ, ապա այս տվյալները SQL հրամաններից տարբերելու համար դրանք պետք է տեղադրվեն չակերտների մեջ։
Օրինակ, եթե գրեք
SELECT * FROM աղյուսակից, որտեղ անունը = Բիլ
այնուհետև տվյալների բազան կորոշի, որ Bill-ը այլ դաշտի անուն է, այն չի գտնի և սխալ կգցի։ Հետևաբար, փոխարինված տվյալները (այս դեպքում՝ Bill անունը) պետք է փակցվեն չակերտների մեջ, այնուհետև տվյալների բազան այն կհամարի տող, որի արժեքը պետք է վերագրվի անվան դաշտին.
SELECT * FROM աղյուսակից WHERE name = «Bill»
Այնուամենայնիվ, մեջբերումները կարող են հայտնվել նաև տվյալների մեջ: Օրինակ,
SELECT * FROM աղյուսակից WHERE name = "D"Artagnan"
Այստեղ տվյալների բազան կորոշի, որ «D»-ն տվյալ է, իսկ Արտագնանը հրաման է, որը նա չգիտի, և նույնպես սխալ կգցի։ Հետևաբար, անհրաժեշտ է հետևել բոլոր տվյալներին, որպեսզի շտեմարանին բացատրվի, որ դրանցում հայտնաբերված չակերտները (և որոշ այլ հատուկ նշաններ) վերաբերում են տվյալներին:
Արդյունքում մենք կստանանք ճիշտ հարցում, որը սխալներ չի առաջացնի.
SELECT * FROM աղյուսակից WHERE name = "D\"Artagnan"
Այսպիսով, մենք պարզեցինք, որ լարային տվյալները հարցման մեջ փոխարինելիս պետք է հետևել երկու կանոն.
- բոլոր տեղադրված տողային տվյալները պետք է փակվեն չակերտների մեջ (մեկ կամ կրկնակի, բայց միայնակները ավելի հարմար են և ավելի հաճախ օգտագործվում):
- հատուկ նիշերը պետք է փախչել շեղերով:
Հարկ է հատուկ նշել. ավելացված շեղերը ՉԵՆ մտնում տվյալների բազա: Դրանք անհրաժեշտ են միայն խնդրանքի մեջ։ Հիմքին հարվածելիս շեղերը հանվում են: Համապատասխանաբար, տարածված սխալն այն է, որ տվյալների բազայից տվյալներ հանելիս օգտագործել stripslashes:
Վերոնշյալ բոլորը վերաբերում են լարային տվյալներին և ամսաթվերին: Թվերը կարող են տեղադրվել առանց հետևելու կամ չակերտներով շրջապատել դրանք: Եթե դուք դա անում եք, ապա ԱՆՀՐԱԺԵՇՏ!ստիպել տվյալները ցանկալի տիպին՝ նախքան դրանք հարցումի մեջ մտցնելը, օրինակ՝
$id = intval ($id);
Այնուամենայնիվ, պարզության (և հուսալիության) համար դուք կարող եք աշխատել թվերի հետ, ինչպես տողերի հետ (քանի որ mysql-ը դեռ փոխակերպում է դրանք ցանկալի տեսակի): Համապատասխանաբար, մենք կհետագծենք հարցումում զետեղված ցանկացած տվյալ և կփակենք այն չակերտների մեջ:
Նաև կա ևս մեկ կանոն՝ կամընտիր, բայց այն պետք է հետևել՝ սխալներից խուսափելու համար.
Դաշտերի և աղյուսակների անունները պետք է փակվեն հետևի մենակ չակերտների մեջ՝ «`» (այս նշանով ստեղնը գտնվում է ստանդարտ ստեղնաշարի վրա՝ «1» ստեղնից ձախ): Ի վերջո, դաշտի անունը կարող է համընկնել mysql-ի հետ: հիմնաբառեր, բայց եթե օգտագործենք հետևի մեջբերում, ապա MySQL-ը կհասկանա, որ ամեն ինչ ճիշտ է.
SELECT * FROM `table` WHERE `date` = "2006-04-04"
Պետք է տարբերել այս չակերտները և չշփոթել մեկը մյուսի հետ։ Պետք է նաև հիշել, որ հետույքներից չեն փախչում շեղերը:
Այսպիսով, մենք սովորեցինք, թե ինչպես ճիշտ փոխարինել տվյալները հարցումով:
ԲԱՅՑ Դինամիկ հարցումների կառուցումը չի սահմանափակվում միայն տվյալների փոխարինմամբ: Հաճախ մենք պետք է փոխարինենք SQL հրամանները և դաշտերի անունները հարցման մեջ: Եվ ահա մենք անցնում ենք անվտանգության թեմային.
SQL Injection-ը հաքերային հարձակման մեթոդ է, երբ սկրիպտին փոխանցված տվյալները փոփոխվում են այնպես, որ այս սկրիպտում ստեղծված հարցումը սկսում է կատարել բոլորովին այլ բան, քան այն նախատեսված էր:
Նման հարձակումներից պաշտպանվելու կանոնները կարելի է բաժանել երկու կետի.
1. Աշխատանք տվյալների հետ.
2. Աշխատեք հարցման հսկիչների հետ:
Վերևում մենք մանրամասն քննարկեցինք առաջին կետը: Կարելի է ասել, որ դա, ըստ էության, պաշտպանություն չէ։ Հարցմանը տվյալներ ավելացնելու կանոններին համապատասխանելը թելադրված է առաջին հերթին SQL SYNTAX-ի պահանջներով։ Եվ որպես կողմնակի ազդեցություն, մենք ունենք նաև պաշտպանություն հաքերից:
Երկրորդ կետը շատ ավելի բարդ է, քանի որ տվյալների վերաբերյալ չկա միասնական ունիվերսալ կանոն. հետադարձ կապը չի պաշտպանի դաշտի անվանումը հաքերների կողմից փոփոխվելուց: Հնարավոր չէ չակերտներ օգտագործել աղյուսակների անունները, SQL հայտարարությունները, LIMIT հրամանի պարամետրերը և այլ հայտարարությունները պաշտպանելու համար:
Հետևաբար, հսկիչ տարրերը հարցման մեջ փոխարինելիս հիմնական կանոնը հետևյալն է.
Եթե Ձեզ անհրաժեշտ է հարցման մեջ դինամիկ կերպով տեղադրել SQL հայտարարություններ կամ դաշտերի, տվյալների բազաների, աղյուսակների անուններ, ապա ոչ մի դեպքում չպետք է դրանք ուղղակիորեն տեղադրեք հարցման մեջ:
Նման հավելումների բոլոր տարբերակները պետք է գրվեն ADVANCE-ով ձեր սցենարում և ընտրվեն՝ ելնելով օգտագործողի մուտքագրածից:
Օրինակ, եթե դուք պետք է օպերատորի կողմից պատվերին փոխանցեք դաշտի անունը, ապա ոչ մի դեպքում չպետք է այն ուղղակիորեն փոխարինեք: Մենք պետք է նախ ստուգենք այն: Օրինակ, ստեղծեք վավեր արժեքների զանգված և այն փոխարինեք հարցման մեջ միայն այն դեպքում, եթե փոխանցված պարամետրը առկա է այս զանգվածում.
$orders =array("name" , "price" , "qty" );
$key = array_search ($_GET["sort"], $ orders));
$orderby = $orders [ $key ];
$ հարցում = «Ընտրեք * «աղյուսակից» ՊԱՏՎԻՐԵԼ ԸՍՏ$orderby ";
Մենք որոնում ենք օգտատիրոջ մուտքագրած բառի նախապես նկարագրված տարբերակների զանգվածը, և եթե գտնում ենք, ընտրում ենք զանգվածի համապատասխան տարրը։ Եթե համընկնում չգտնվի, կընտրվի զանգվածի առաջին տարրը:
Այսպիսով, հարցման մեջ փոխարինվում է ոչ թե այն, ինչ մուտքագրել է օգտատերը, այլ այն, ինչ գրված է մեր սցենարում:
Նույնը պետք է արվի մնացած բոլոր դեպքերում։
Օրինակ, եթե WHERE դրույթը դինամիկ ձևավորվում է.
if (!empty($_GET [ "price"])) $where .= "price="" . mysql_real_escape_string ($_GET [ "price" ]). """ ;
$query = "SELECT * FROM `աղյուսակից` WHERE $where " ;
Ինձ համար դժվար է պատկերացնել մի դեպք, երբ աղյուսակի անունը կարող է դինամիկ կերպով տեղադրվել հարցման մեջ, բայց եթե դա տեղի ունենա, ապա անունը նույնպես պետք է տեղադրվի միայն սցենարում նախապես սահմանված հավաքածուից:
LIMIT օպերատորի պարամետրերը պետք է փոխարկվեն ամբողջ թվով տիպի՝ օգտագործելով թվաբանական գործողություններ կամ intval() ֆունկցիան:
Մի կարծեք, որ այստեղ թվարկված օրինակները սպառում են դինամիկ հարցումների կառուցման բոլոր տարբերակները: Պարզապես պետք է հասկանալ սկզբունքը և կիրառել այն բոլոր նման դեպքերում։
Իմ աշխատանքի բնույթից ելնելով, ես պետք է կատարեմ վեբ հավելվածների սկզբնական կոդի անվտանգության աուդիտ:
Շատ վեբ հավելվածներ և շատ կոդ...
Գաղտնիք չէ, որ SQL ներարկման խոցելիությունը ամենատարածվածն է սերվերի կողմից վեբ հավելվածի բոլոր խոցելիություններից: Կան հարթակներ և շրջանակներ, որտեղ նման բաները գրեթե ամբողջությամբ բացառված են, օրինակ ORM-ը և այլն: Բայց վիճակագրությունը մեզ համառորեն պատմում է համացանցում պարզ միացված SQL հարցումներով վեբ հավելվածների բացարձակ գերակշռության մասին: Բացի այդ, կան դեպքեր, երբ ORM-ը ընդհանուր առմամբ կիրառելի Այն չի կարող, օրինակ, երբ ոչ միայն արտահայտությունների պարամետրերը, այլ նաև հարցման տրամաբանությունը օպերատորի մակարդակում պետք է կախված լինեն օգտվողի տվյալներից:
Այսպիսով, եկեք սկսենք:
Անօգուտ կերպարի փախչում
Հայտնաբերվել է PHP վեբ հավելվածների 83%-ում, որոնք խոցելի են SQL ներարկումների նկատմամբ
Օգտագործելով փախուստի գործառույթը այնպիսի նիշերի համար, ինչպիսիք ենmysql_escape_string
mysql_real_escape_string
հավելումներ
առանց չակերտների. Ամենից հաճախ այն արտահայտվում է թվային պարամետրերով (բոլոր տեսակի *_id):
Օրինակ
$sql = "Ընտրել օգտվողին օգտվողների ցուցակից WHERE userid=".mysql_real_escape_string($_GET["uid"]);Թվում է, թե դա անվտանգ կոդ է, բայց միայն մակերեսային: SQL ներարկումների ամենատարածված օրինակը PHP-ում իմ պրակտիկայում հայտնվեց այստեղ: Այս խոցելիության վրա հարձակվելու համար հարձակվողը պարզապես պետք է խուսափի հարձակման վեկտորում \x00 \r \n \x1a նիշերի օգտագործումից։
Օրինակ:
/index.php?uid=-777 UNION SELECT գաղտնաբառը օգտվողների ցանկից
Որոնել կոդով
Բարդացած է լեզվի իմաստաբանությամբ։ Պարզ որոնման համար կարող եք օգտագործել egrep.egrep -Rin "(ընտրել|թարմացնել|տեղադրել|ջնջել|փոխարինել).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" : | grep -v "[\""]["\"]"
Որոնման արտահայտության տրամաբանությունը հետևյալն է՝ գտնել բոլոր տողերը, որոնցում զտիչ ֆունկցիաներից ձախ կողմում չկա չակերտների ("", "", "", "") նիշերի հաջորդականություն: Մեթոդը, իհարկե, հեռու է 100%-ից, բայց իմաստային վերլուծություն կատարելու համար անհնար է կանոնավոր արտահայտություն պահանջել։
Տեղեկությունների ցուցադրումն ավելի դյուրին դարձնելու համար վահանակում կարող եք գույնով ընդգծել ֆունկցիան.
egrep -Rin "(ընտրել|թարմացնել|տեղադրել|ջնջել|փոխարինել).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" : | grep -v "[\""]["\"]" | egrep --color "(mysql_escape_string|mysql_real_escape_string|addslashes)"
Այս նշանի խոցելիությունից պաշտպանվելու համար ավելի լավ է օգտագործել տիպի ձուլումը:
Սա միշտ աշխատում է ավելի արագ և ավելի հուսալի, քան բոլոր տեսակի զտումները և զննումները:
Վերոնշյալ օրինակի համար կարկատելը կարող է այսպիսին լինել.
$sql = "Ընտրել օգտվողին օգտվողների ցուցակից WHERE userid=".intval($_GET["uid"]);
Սա եզրափակում է կարճ շարադրանքը: Ես կոչ եմ անում բոլոր վեբ մշակողներին փորձել ստուգել իրենց աղբյուրները նման ձևավորումների համար: Ավելի լավ է ընդլայնել մարդկանց որոնման տվյալ սցենարը:
Այսպիսով, ես հիմնականում խորը փորել եմ MySQL-ի և PHP-ի տարածքները... մասնավորապես անվտանգության միջոցները, որոնք ես պետք է ձեռնարկեմ տվյալների բազայի հետ գործ ունենալիս և ձևաթղթերի մուտքագրումներին: Մինչ այժմ ես գտել եմ հետևյալը, որոնք խիստ խորհուրդ են տրվում.
- Պատրաստված հայտարարություններ
- Օգտագործելով _real_escape_string()
- ՉՕԳՏԱԳՈՐԾԵԼ Կախարդական մեջբերումներ, քանի որ այն շփոթում է տվյալների շտեմարանները և վերջում տալիս ձեզ այնպիսի բաներ, ինչպիսիք են «Դու չես անվանել…»:
Այս ամենը հիանալի է, և ես հետևում եմ դրան: Այնուամենայնիվ, ես մտածում էի, թե արդյոք պետք է խուսափել այնպիսի նիշերից, ինչպիսիք են դոլարի նշանը [$], տոկոսի նշանը [%] և, հավանաբար, ուրիշները: Կարո՞ղ էր հարցումը մեկնաբանել դոլարի նշանը որպես PHP փոփոխական: Ի՞նչ կասեք LIKE շարահյուսության մասին, որը ես լսել եմ, որ օգտագործում է % խորհրդանիշը կամ նույնիսկ նիշը: Պատրաստված հայտարարությունները տեխնիկապես պետք է հոգ տան այս ամենի մասին, բայց ես պարզապես ցանկանում էի լինել ապահով կողմում և համոզվել, որ ամեն ինչ պատշաճ կերպով լուսաբանել եմ: Այն դեպքերում, երբ ես մոռանում եմ օգտագործել պատրաստված հայտարարությունները կամ պարզապես անտեսում եմ դրանք, ես հույս ունեի, որ պաշտպանության այս երկրորդ գիծը կարող է ինձ ասել, որ ես կարող եմ ազատվել գլխապտույտից:
Ահա թե ինչ եմ ես ներկայումս օգտագործում փախչելու համար.
Escape ($connect, $data) ($new_data = կրճատում ($data); $new_data = i_real_escape_string ($connection, $new_data); $new_data = addcslashes ($new_data, "%_$"); $new_data = htmlspecialchars ($new_data, ENT_NOQUOTES); վերադարձնել $new_data;)
Այսպիսով, սա ճի՞շտ է: Ես սարսափելի սխալ բան եմ անում: Խնդրում ենք նկատի ունենալ, որ տվյալների բազայի տվյալները վերադարձնելու ժամանակ ես պետք է հեռացնեմ $,% և _ նիշերից առաջ ետ կտրվածքը:
Ես սարսափելի սխալ բան եմ անում:
Նախ ձեր հետազոտության մասին:
Պատրաստված հայտարարություններ – միակըհրաշալի բան, որ գտել ես:
Չնայած mysqli_real_escape_string-ի օգտագործումը (ենթադրելով, որ դուք օգտագործում եք պատրաստված հայտարարություններ) կլինի անօգուտ և վնասակար(ստեղծելով արդյունք, որը դուք ինքներդ նշել եք. «Դուք զանգել եք չէ...»):
Իսկ Magic Quotes-ը վաղուց հեռացվել է լեզվից, ուստի իրականում ոչինչ չարժե:
Այսպիսով, նույնիսկ ձեր սկզբնական տարածքների մեծ մասը ակնհայտորեն սխալ է:
Հիմա ձեր հարցին.
Կարո՞ղ էր հարցումը մեկնաբանել դոլարի նշանը որպես PHP փոփոխական:
Ի՞նչ կասեք LIKE շարահյուսության մասին, որը ես լսել եմ, որ օգտագործում է % խորհրդանիշը կամ նույնիսկ նիշը:
Այո, դուք ճիշտ եք լսել: LIKE օպերատորի ճշգրիտ նպատակը օրինաչափությունների որոնում կատարելն է: Այս նիշերն անջատելը LIKE-ով մի փոքր իմաստ չի ունենա:
Ամեն անգամ, երբ դուք պատրաստվում եք օգտագործել LIKE օպերատորը, դուք պետք է որոշեք, թե կոնկրետ որ նիշն օգտագործել և որը արգելել: Դուք չեք կարող օգտագործել մեկանգամյա լուծում: Էլ չեմ ասում, որ մնացած բոլոր mysql փոխազդեցություններում % նշանը հատուկ նշանակություն չունի։
Պատրաստված հայտարարությունները տեխնիկապես պետք է հոգ տան այս ամենի մասին
Պատրաստված հայտարարությունները ոչ մի կապ չունեն $ կամ % նշանների հետ: Պատրաստված հայտարարությունները վերաբերում են SQL ներարկմանը, բայց ոչ մի նիշ չի կարող առաջացնել այն (դուք չէիք կարող «ներարկումը» անվանել ճիշտ օգտագործված LIKE օպերատոր, չէ՞):
Վերջապես, ամենավատը:
Եթե մոռանում եք օգտագործել պատրաստված հայտարարությունները կամ պարզապես անտեսում եք դրանց հետևելը,
ոչինչ քեզ չի փրկի:
Եվ նվազագույն օգնությունը կլինի ձեր մշակած գործառույթից:
Ամփոփել.
- Ազատվեք այս հատկությունից։
- Օգտագործեք լցոնիչներ *յուրաքանչյուր առանձին փոփոխական ներկայացնել հարցումում:
- Escape % և _ նիշերը մուտքագրում միայն այն դեպքում, եթե դրանք կօգտագործվեն LIKE օպերատորում, և դուք չեք ցանկանում, որ դրանք մեկնաբանվեն:
- Օգտագործեք htmlspecialchars() ելքի համար, ոչ թե mysql մուտքագրման համար:
*կարդացեք պատրաստված հայտարարությունները, եթե այս տերմինը ձեզ անծանոթ է:
Պետք չէ խուսափել դոլարի նշանից։ MySQL-ը հատուկ չի նայում այս նիշին, և PHP-ն ճանաչում է այն միայն սկզբնական կոդով, այլ ոչ թե լարային արժեքներով (եթե տողի վրա չկոչես eval, բայց դա որդերի լրիվ այլ ճիճու է):
Դուք միայն պետք է փախչեք % և _-ից, եթե օգտագործեիք օգտվողի մուտքագրումը որպես LIKE արգումենտ և չցանկանաք, որ օգտվողը կարողանա օգտագործել wildcards: Դա կարող է տեղի ունենալ, եթե դուք մշակում եք որոնման ձևը: Ձեզ անհրաժեշտ չէ օգտագործել այն տվյալների բազայում պահելիս:
Տվյալների բազա մուտք գործելիս ձեզ հարկավոր չէ օգտագործել htmlspecialchars: Սա պետք է օգտագործվի միայն HTML էջում օգտագործողին տվյալները ցուցադրելիս՝ XSS ներարկումը կանխելու համար:
Նայած, թե ինչ տվյալներ և ինչի համար են դրանք օգտագործվում։
Եթե գտնում եք, որ PHP-ի լռելյայն դրույթները չափազանց մեծ են և բարդ, ես առաջարկում եմ դիտել github-ում առկա որոշ դասեր՝ պարզեցված հարցումների մասին պատկերացում կազմելու համար:
Այս դասի հետ հարցումներ տեղադրելու օրինակ
$data = Array ("login" => "admin", "active" => true, "firstName" => "John", "lastName" => "Doe", "password" => $db->func( "SHA1(?)",Զանգված ("գաղտնի գաղտնաբառ+աղ")), // գաղտնաբառ = SHA1("գաղտնաբառ+աղ") "createdAt" => $db->now(), // createAt = NOW() " expires" => $db->now("+1Y") // expires = NOW() + ընդմիջում 1 տարի // Աջակցվող միջակայքերը [վրկ] վայրկյան, [մ] րոպե, [ժ] ժամ, [d] օր, [M]ամսական, [Y] ականջ); $id = $db->insert("users", $data); եթե ($id) echo "user-ը ստեղծվել է. Id=" . $id; else echo «ներդիրը ձախողվեց.» . $db->getLastError();