ترميز وفك تشفير
من خلال الشكل التالي ، يمكننا أن نفهم أين يوجد ترميز في Javaweb:
يريد المستخدم أن يرسل الخادم طلب HTTP. الأماكن التي تكون فيها الترميز هي عنوان URL وملفات تعريف الارتباط والمعلمة. بعد الترميز ، يقبل الخادم طلب HTTP ، ويقوم بتخفيض طلب HTTP ، ثم يفكّر عنوان URL وملفات تعريف الارتباط والمعلمة. أثناء معالجة منطق أعمال الخادم ، قد يكون من الضروري قراءة قواعد البيانات أو الملفات المحلية أو الملفات الأخرى في الشبكة ، وما إلى ذلك ، وتتطلب هذه العمليات الترميز وفك التشفير. بعد اكتمال المعالجة ، يقوم الخادم بترميز البيانات ويرسلها إلى العميل ، ويعرضها المتصفح إلى المستخدم بعد فك التشفير. هناك العديد من الترميز وفك التشفير المشاركين في هذه العملية برمتها ، والمكان الأكثر ترجيحًا للظهور هو عملية التفاعل مع الخادم والعميل.
يمكن تلخيص العملية بأكملها أعلاه على النحو التالي: يتم تمرير البيانات المشفرة للصفحة إلى الخادم ، ويكشف الخادم البيانات التي تم الحصول عليها ، وبعد بعض معالجة منطق العمل ، يتم تشفير النتيجة النهائية ومعالجتها ، ويقوم العميل بفك تشفيرها ويعرضها على المستخدم. لذا ، سأطلب تفسيرًا لترميز وفك تشفير Javaweb.
إذا أراد العميل أن يرسل الخادم طلبًا ، فسيمرر أربع حالات:
1. الوصول المباشر عن طريق عنوان URL.
2. رابط الصفحة.
3. النموذج الحصول على الخضوع
4. شكل ما بعد التقديم
طريقة عنوان URL: بالنسبة إلى عناوين URL ، إذا كانت جميع عناوين URL باللغة الإنجليزية ، فلا توجد مشكلة. إذا كان هناك صيني ، فسيشارك الترميز. كيف ترميز؟ ما هي القواعد التي تريد تشفيرها؟ فكيف فك تشفيره؟ سيتم الرد على الإجابات واحدة تلو الأخرى! انظر أولاً إلى مكونات عنوان URL:
في عنوان URL هذا ، سيقوم المتصفح بتشفير المسار والمعلمة. لشرح عملية الترميز بشكل أفضل ، استخدم عنوان URL التالي
http://127.0.0.1:8080/perbank/i am cm؟ name = أنا cm
أدخل العنوان أعلاه في مربع إدخال عنوان URL للمتصفح. من خلال عرض معلومات رأس رسالة HTTP ، يمكننا أن نرى كيف يقوم المتصفح بتشفيرها. فيما يلي شروط الترميز لثلاثة متصفحات:
يمكنك أن ترى أن ترميز "أنا" من المتصفحات الرئيسية هو كما يلي:
جزء المسار | سلسلة الاستعلام | |
Firefox | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
الكروم | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
أي | E6 88 91 E6 98 AF | CE D2 CA C7 |
void محمي Converturi (messageBytes URI ، طلب طلب) يلقي الاستثناء {bytechunk bc = uri.getbytechunk () ؛ طول int = bc.getLength () ؛ charchunk cc = uri.getcharchunk () ؛ cc.allocate (الطول ، -1) ؛ سلسلة enc = connector.getUrienCoding () ؛ // احصل على مجموعة فك تشفير URI if (enc! = null) {b2cconverter conv = request.getUricOnverter () ؛ حاول {if (conv == null) {conv = new b2cconverter (enc) ؛ request.setUricOnverter (conv) ؛ }} catch (ioException e) {...} if (conv! = null) {try {conv.convert (bc ، cc ، cc.getBuffer (). length - cc.getend ()) ؛ uri.setchars (cc.getBuffer () ، cc.getStart () ، cc.getLength ()) ؛ يعود؛ } catch (ioException e) {...}}} // الترميز الافتراضي: تحويل سريع بايت [] bbuf = bc.getBuffer () ؛ char [] cbuf = cc.getBuffer () ؛ int start = bc.getStart () ؛ لـ (int i = 0 ؛ i <length ؛ i ++) {cbuf [i] = (char) (bbuf [i+start] & 0xff) ؛ } uri.setchars (cbuf ، 0 ، طول) ؛ } من الكود أعلاه ، يمكننا أن نرى أن عملية فك تشفير URI هي أولاً الحصول على مجموعة فك التشفير للموصل ، الذي تم تكوينه في server.xml
<connector uriencoding = "utf-8" />
إذا لم يتم تعريفها ، فسيتم استخدام الترميز الافتراضي ISO-8859-1 للحلية.
بالنسبة لجزء سلسلة الاستعلام ، نعلم أنه سواء كنا نرسله من خلال GET أو POST ، يتم حفظ جميع المعلمات في المعلمات ، ثم نستخدم طلب. داخل طريقة getParameter ، يطلق على طريقة parseparameters من org.apache.catalina.connector.request ، والتي ستقوم بفك تشفير المعلمات التي تم تمريرها. الرمز التالي هو مجرد جزء من طريقة parseparameters:
// الحصول على سلسلة الترميز enc = getCharacterEncoding () ؛ // احصل على charset boolean المحددة في contentType usebodyencodingforuri = connector.getuseBodyenCodingforuri () ؛ if (enc! = null) {// إذا لم يكن الترميز فارغًا ، فقم بتعيين الترميز على enc parameters.setencoding (enc) ؛ if (usebodyencodingforuri) {// إذا تم تعيين المخطط ، فقم بتعيين فك تشفير QueryString إلى chartset parameters.setquerystringencoding (enc) ؛ }} else {// قم بتعيين معلمات طريقة فك التشفير الافتراضية. if (usebodyencodingforuri) {parameters.setquerystringencoding (org.apache.coyote.constants.default_character_encoding) ؛ }} من الكود أعلاه ، يمكننا أن نرى أن تنسيق فك التشفير لسلسلة الاستعلام يستخدم إما Set ChartSet أو يستخدم تنسيق فك التشفير الافتراضي ISO-8859-1. لاحظ أن المخطط في هذا الإعداد هو ContentType المحدد في رأس HTTP. في الوقت نفسه ، إذا احتجنا إلى تغيير السمة المحددة ليتحول ، نحتاج إلى تكوين ما يلي:
<connector uriencoding = "utf-8" useBodyenCodingforuri = "true"/>
يقدم الجزء أعلاه عملية الترميز وفك التشفير لطلبات URL بالتفصيل. في الواقع ، بالنسبة لنا ، فإن طرقنا الإضافية هي تقديمها في النموذج.
شكل الحصول على
نحن نعلم أن إرسال البيانات من خلال عناوين URL من السهل التسبب في مشاكل رمز مشجعة ، لذلك نميل إلى استخدام نماذج النماذج. عندما ينقر المستخدم على إرسال النموذج ، سيقوم المتصفح بتعيين المزيد من الرموز لتمرير البيانات إلى الخادم. يتم تقطيع البيانات المقدمة من خلال GET بعد عنوان URL (هل يمكن اعتباره سلسلة استعلام ؟؟) ، لذلك يلعب UrienCoding دورًا في عملية فك تشفير خادم Tomcat. سيقوم خادم Tomcat بفك تشفيره وفقًا لمجموعة UrienCoding ، وإذا لم يتم تعيينه ، فسيستخدم ISO-8859-1 الافتراضي. إذا قمنا بتعيين الترميز على UTF-8 على الصفحة ، ولم يتم تعيين uriencoding أو لم يتم تعيينه ، فسيحدث رمز مشجاع عند فك تشفير الخادم. في هذا الوقت ، يمكننا عمومًا الحصول على البيانات الصحيحة من خلال شكل سلسلة جديدة (request.getParameter ("name"). getBytes ("ISO-8859-1") ، "UTF-8").
شكل آخر
بالنسبة لطريقة النشر ، يتم تحديد الترميز الذي يستخدمه أيضًا بواسطة الصفحة ، أي ContentType. عندما أقوم بإرسال نموذج بالنقر فوق الزر "إرسال" على الصفحة ، سيقوم المتصفح أولاً بتشفير معلمات نموذج النشر وفقًا لتنسيق ترميز charset الخاص بـ ontenttype وإرساله إلى الخادم. على جانب الخادم ، يستخدم أيضًا مجموعة الأحرف في ContentType لفك التشفير (يختلف عن طريقة GET هنا). هذا يعني أن المعلمات المقدمة من خلال نموذج البريد عمومًا لا تعاني من مشاكل مشوهة. بالطبع ، يمكننا تعيين مجموعة الأحرف التي ترميز أنفسنا: request.setcharacterencoding (Charset).
حل مشكلة عناوين URL المشوهة باللغة الصينية
نرسل بشكل أساسي طلبات إلى الخادم من خلال نموذجين من التقديم: URL والشكل. النموذج عمومًا لا يعاني من مشاكل مشوهة ، والمشاكل المشوهة على عنوان URL بشكل أساسي. من خلال إدخال المدونات السابقة ، نعلم أن عملية إرسال الطلب الترميز إلى الخادم بواسطة عنوان URL أمر مربك للغاية. ستؤدي أنظمة التشغيل المختلفة والمتصفحات المختلفة ومجموعات أحرف الويب المختلفة إلى نتائج تشفير مختلفة تمامًا. أليس الأمر مخيفًا للغاية إذا أراد المبرمجون أخذ كل نتيجة في الاعتبار؟ هل هناك طريقة للتأكد من أن العميل يستخدم طريقة ترميز واحدة فقط لإصدار طلب إلى الخادم؟
يملك! هنا أقدم الأساليب التالية بشكل أساسي
جافا سكريبت
استخدام ترميز JavaScript لا يمنح المتصفح فرصة للتدخل. بعد الترميز ، أرسل طلبًا إلى الخادم ثم فك تشفيره في الخادم. عند إتقان هذه الطريقة ، نحتاج إلى ثلاث طرق لترميز JavaScript: Escape () و Encodeuri () و EncodeUricomponent ().
يهرب
يتم ترميز السلسلة المحددة باستخدام مجموعة الأحرف اللاتينية SIO. يتم تشفير جميع الأحرف غير ASCII كسلاسل بتنسيق ٪ XX ، حيث يمثل XX الرقم السداسي المقابل للحرف في مجموعة الأحرف. على سبيل المثال ، الترميز المقابل للتنسيق هو ٪ 20. طريقة فك التشفير المقابلة هي unescape ().
في الواقع ، لا يمكن استخدام Escape () مباشرة لتشفير عنوان URL ، وتتمثل وظيفتها الحقيقية في إرجاع القيمة المشفرة أحادية الطابع. على سبيل المثال ، تكون نتيجة "I am cm" أعلاه ٪ U6211 ٪ U662FCM ، حيث يكون الترميز المقابل لـ "I" 6211 ، وترميز "نعم" هو 662F ، وترميز "CM" هو CM.
لاحظ أن Escape () غير مشفر بواسطة "+". لكننا نعلم أنه عندما تقدم صفحة الويب نموذجًا ، إذا كانت هناك مسافات ، فسيتم تحويلها إلى أحرف +. عندما يقوم الخادم بمعالجة البيانات ، ستتم معالجة علامة + في مسافات. لذلك ، كن حذرا عند استخدامه.
Encodeuri
ترميز عنوان URL بأكمله ، يستخدم تنسيق UTF-8 لإخراج السلسلة المشفرة. ومع ذلك ، لن يقوم Encodeuri بتشفير بعض الأحرف الخاصة باستثناء ترميز ASCII ، مثل:! @ # $ & * () =: / ؛ ؟ + '.
المكون EncodeUricompon
تحويل سلاسل URI إلى سلاسل تنسيق الهروب بتنسيق ترميز UTF-8. بالمقارنة مع Encodeuri ، سيكون EncodeUricomponent أكثر قوة ، وسيتم ترميزه للرموز (؛ /؟: @ & = + $ ، #) التي لم يتم ترميزها في Encodeuri (). ومع ذلك ، فإن EncodeUricomponent لن يقوم فقط بتشفير مكونات عنوان URL بشكل فردي ، ولن يتم استخدامه لترميز عنوان URL بالكامل. طريقة دالة فك تشفير المقابلة.
بالطبع ، نستخدم عادة حزب Encodeuri لأداء عمليات الترميز. إن ما يسمى بترميز JavaScript وفك تشفيره مرتين في الخلفية هو استخدام هذه الطريقة. هناك حلان لحل هذه المشكلة في JavaScript: Transcode و اثنين من طريقتان الترميز.
ترميز مرة واحدة
ترميز JavaScript:
var url = '<s: property value = "webpath" />/showmoBlieQrcode.Servlet؟name=i am cm' ؛ window.location.href = encodeuri (url) ؛
URL Transcoded: http://127.0.0.1:8080/perbank/ShowMoBlieQrcode.Servlet؟name=٪E6٪88٪91٪E6٪98٪AFCM
معالجة الخلفية:
اسم السلسلة = request.getParameter ("name") ؛ System.out.println ("المعلمات الواردة المقدمة:" + name) ؛ name = new string (name.getBytes ("ISO-8859-1") ، "UTF-8") ؛ system.out.println ("المعلمات decoded:" + name) ؛ نتيجة الإخراج:
المعلمات الواردة في مكتب الاستقبال: ؟؟؟؟؟؟
بعد فك تشفير المعلمات: أنا سم
الترميز الثانوي
جافا سكريبت
var url = '<s: property value = "webpath" />/showmoBlieQrcode.Servlet؟name=i am cm' ؛ window.location.href = encodeuri (encodeuri (url)) ؛
URL TranscoDed:
معالجة الخلفية:
اسم السلسلة = request.getParameter ("name") ؛ System.out.println ("المعلمات الواردة المقدمة:" + name) ؛ name = urldecoder.decode (name ، "utf-8") ؛ system.out.println ("المعلمات decoded:" + name) ؛ نتيجة الإخراج:
المعلمات الواردة في الواجهة الأمامية: E68891E698AFCM
بعد فك تشفير المعلمات: أنا سم
فلتر
باستخدام المرشحات ، توفر المرشحات نوعين ، الأول هو تعيين الترميز ، والثاني هو إجراء عمليات فك التشفير مباشرة في المرشح.
مرشح 1
يعين هذا المرشح مباشرة تنسيق الترميز للطلب.
طبقة الطبقة العامة تنفس الأدوات تصفية {private filterConfig config ؛ سلسلة ترميز = فارغة ؛ void public dorder () {config = null ؛ } public void dofilter (طلب servletRequest ، استجابة servletResponse ، سلسلة filterchain) يلقي ioException ، servleTexception {request.setcharacterencoding (الترميز) ؛ Chain.dofilter (طلب ، استجابة) ؛ } public void init (filterConfig config) يلقي servleTexception {this.config = config ؛ // الحصول على معلمات التكوين string str = config.getInitParameter ("الترميز") ؛ if (str! = null) {الترميز = str ؛ }}} إعدادات:
<!-تكوين المرشح الصيني-> <filter> <filter-name> الصينيات </filter-name> <ilter-class> com.test.filter.characterencoding </filter-class> <Ing-param> <bar-name> الترميز </param-name> <barm-value> utf-8 <filter-name> الصينييندوينج </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
مرشح 2
في طريقة المعالجة ، يقوم المرشح بفك تشفير المعلمات مباشرة ، ثم يعيد تعيين المعلمات التي تم فك تشفيرها إلى سمة الطلب.
طبقة الطبقة العامة الأدوات مرشح {FilterConfig FilterConfig المحمية ؛ سلسلة ترميز = فارغة ؛ void public dorder () {this.filterConfig = null ؛ } / *** تهيئة* / public void init (filterConfig filterConfig) {this.filterConfig = filterConfig ؛ } / *** تحويل instr إلى نموذج ترميز UTF -8** param instrate enter string* @REGRUNT UTF - سلسلة ترميز 8* throws unsupportedencodingexception* / private string toutf (string instr) يلقي unsupportedEncodingException {String outstr = "" ؛ if (instr! = null) {Outstr = new string (instr.getBytes ("ISO-8859-1") ، "UTF-8") ؛ } إرجاع Outstr ؛ } / *** معالجة التصفية الصينية المشوهة* / public void dofilter (servletrequest servletrequest ، servletResponse ServletResponse ، سلسلة filterchain) يلقي iOexception ، servleTexception {httpservletrequest request = (httpservledrequest) servleTrequest ؛ httpservletresponse استجابة = (httpservletresponse) servletResponse ؛ // طريقة الحصول على الطلب (1.post أو 2.get) ، ويتم تنفيذ معالجة مختلفة وفقًا لطرق سلسلة طرق مختلفة = request.getMethod () ؛ // 1. للطلبات المقدمة في المنشور ، قم بتعيين الترميز مباشرة على UTF-8 if (method.equalsignorecase ("post")) {try {request.setcharacterencoding ("utf-8") ؛ } catch (UnsupportedEncodingException e) {E.PrintStackTrace () ؛ }} // 2. طلب تم إرساله في GET else {// الحصول على إخراج مجموعة المعلمة المقدمة من تعداد العميل <Tring> paramnames = request.getParameTernames () ؛ . // احصل على قيم سلسلة اسم المعلمة [] = request.getParamEtervalues (name) ؛ // خذ قيمتها وفقًا لاسم المعلمة // إذا لم تكن مجموعة قيمة المعلمة فارغة إذا (القيم! = null) {// اجتياز قيمة المعلمة تعيين (int i = 0 ؛ i <border.length ؛ i ++) {try {// circle back and call calle tuoutf (abord [i]) method to thending the paraction strup strup vlust = toutf ؛ القيم [i] = vlustr ؛ } catch (UnsupportedEncodingException e) {E.PrintStackTrace () ؛ }} // إخفاء القيمة في نموذج سمة في طلب الطلب. }}} // قم بتعيين طريقة الاستجابة ودعم مجموعة الأحرف الصينية. // تواصل تنفيذ المرشح التالي. إذا لم يكن هناك مرشح ، فسيكون الطلب chain.dofilter (طلب ، استجابة) ؛ }} إعدادات:
<!-تكوين المرشح الصيني-> <filter> <filter-name> الصينيين </filter-name> <lipter-class> com.test.filter.characterencoding </filter-class> </filter> </filter-mapping> <filter-name> الصينية </filter-name>
آخر
1. تعيين pageencoding و contentType
أقل
2. قم بإعداد uriencoding من tomcat
بشكل افتراضي ، يستخدم خادم TomCat تنسيق الترميز ISO-8859-1 لترميز عنوان URL المطلوب بواسطة معلمة uriencoding ، لذلك نحتاج فقط إلى إضافة uriencoding = "UTF-8" إلى <sonnector> علامة ملف server.xml من tomcat.