Եվ նվազագույն օգնությունը կլինի ձեր մշակած գործառույթից: 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»)

Այստեղ կային շատ օգտակար պատասխաններ, որոնք ընդհանուր առմամբ ավարտվում էին երկու կետով:

  1. BACKTICKS (`) օգտագործվում են նույնացուցիչների անունների շուրջ:
  2. ՄԵԿ ՄԵՋԱԿՏԵՐ (") օգտագործվում են արժեքների շուրջ:

Եվ ինչպես @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-ում գնանշումների երկու տեսակ կա.

  1. « ներառել լարային բառացիները
  2. ` ներառել նույնացուցիչներ, ինչպիսիք են աղյուսակների և սյունակների անունները

Եվ հետո կա «սա հատուկ դեպք է, այն կարող է օգտագործվել մեկվերը նշված թիրախներից միաժամանակ՝ կախված սերվերի sql_mode-ից.

  1. Կանխադրված«նիշը» կարող է օգտագործվել լարային տառերի բույն դնելու համար»
  2. 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 եթե ($i==0)
$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-ի տարածքները... մասնավորապես անվտանգության միջոցները, որոնք ես պետք է ձեռնարկեմ տվյալների բազայի հետ գործ ունենալիս և ձևաթղթերի մուտքագրումներին: Մինչ այժմ ես գտել եմ հետևյալը, որոնք խիստ խորհուրդ են տրվում.

  1. Պատրաստված հայտարարություններ
  2. Օգտագործելով _real_escape_string()
  3. ՉՕԳՏԱԳՈՐԾԵԼ Կախարդական մեջբերումներ, քանի որ այն շփոթում է տվյալների շտեմարանները և վերջում տալիս ձեզ այնպիսի բաներ, ինչպիսիք են «Դու չես անվանել…»:

Այս ամենը հիանալի է, և ես հետևում եմ դրան: Այնուամենայնիվ, ես մտածում էի, թե արդյոք պետք է խուսափել այնպիսի նիշերից, ինչպիսիք են դոլարի նշանը [$], տոկոսի նշանը [%] և, հավանաբար, ուրիշները: Կարո՞ղ էր հարցումը մեկնաբանել դոլարի նշանը որպես 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 օպերատոր, չէ՞):

Վերջապես, ամենավատը:

Եթե ​​մոռանում եք օգտագործել պատրաստված հայտարարությունները կամ պարզապես անտեսում եք դրանց հետևելը,

ոչինչ քեզ չի փրկի:

Եվ նվազագույն օգնությունը կլինի ձեր մշակած գործառույթից:

Ամփոփել.

  1. Ազատվեք այս հատկությունից։
  2. Օգտագործեք լցոնիչներ *յուրաքանչյուր առանձին փոփոխական ներկայացնել հարցումում:
  3. Escape % և _ նիշերը մուտքագրում միայն այն դեպքում, եթե դրանք կօգտագործվեն LIKE օպերատորում, և դուք չեք ցանկանում, որ դրանք մեկնաբանվեն:
  4. Օգտագործեք 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();