ในช่วงไม่กี่ปีที่ผ่านมาการใช้รหัส QR นั้นมีความเจริญรุ่งเรืองมากขึ้นเรื่อย ๆ เมื่อเร็ว ๆ นี้ฉันได้พบงานที่ต้องใช้การสแกนรหัส QR เพื่อเข้าสู่เว็บไซต์ ดังนั้นฉันได้ศึกษากลไกนี้และใช้กระบวนการทั้งหมดด้วยรหัส ต่อไปฉันจะคุยกับคุณเกี่ยวกับการเข้าสู่ระบบรหัส QR และสิ่งอื่น ๆ
หลักการของรหัส QR
รหัส QR ถูกสร้างขึ้นโดย WeChat เมื่อเราสแกนรหัส QR บน WeChat เรารู้สึกวิเศษมากเมื่อเราลงชื่อเข้าใช้หน้าเว็บของ WeChat อย่างไรก็ตามหลังจากที่เราเข้าใจหลักการของมันมันไม่ได้มีมนต์ขลัง รหัส QR มีข้อมูลคำขอ URL ผ่านเมทริกซ์ DOT ขาวดำ สแกนรหัสบนเทอร์มินัลขอ URL และดำเนินการที่เกี่ยวข้อง
หลักการของการดำเนินการสแกนรหัสทั่วไป
นี่คือหลักการของ WeChat Login และ Alipay Scanning Code Payment:
1. ขอรหัส QR
เดสก์ท็อปเริ่มต้นคำขอรหัส QR ไปยังเซิร์ฟเวอร์
2. สร้างรหัส QR ด้วยรหัสที่ไม่ซ้ำกัน
เดสก์ท็อปจะสร้าง ID แบบสุ่มและ ID จะระบุรหัส QR นี้โดยเฉพาะสำหรับการดำเนินการที่ตามมา
3. สแกนรหัสบนกระดาน
สแกนรหัส QR บนเทอร์มินัลมือถือเพื่อแก้ไขคำขอ URL ในรหัส QR
4. เทอร์มินัลมือถือส่งคำขอไปยังเซิร์ฟเวอร์
เทอร์มินัลมือถือส่งคำขอ URL ไปยังเซิร์ฟเวอร์ซึ่งมีข้อมูลสองอย่าง ID ที่ไม่ซ้ำกันระบุว่ารหัสใดถูกสแกนและพารามิเตอร์คุกกี้หรือส่วนหัวเฉพาะในเบราว์เซอร์บนเทอร์มินัลจะระบุว่าผู้ใช้สแกนรหัสใด
5. การแจ้งเตือนฝั่งเซิร์ฟเวอร์เพื่อสแกนรหัสสำเร็จ
เมื่อเซิร์ฟเวอร์ได้รับคำขอ URL สำหรับข้อมูลในรหัส QR ด้านการแจ้งเตือนได้สแกนรหัสสำเร็จและเพิ่มคุกกี้เข้าสู่ระบบและข้อมูลอื่น ๆ ที่จำเป็น โดยทั่วไปมีวิธีการแจ้งเตือนหลายวิธีที่นี่: WebSocket, การฝึกอบรมถือคำขอจนกว่าจะหมดเวลาและการฝึกอบรมใช้เวลาหลายวินาที
ศิลปะของ URL ในรหัส QR
วิธีตระหนักถึงความแตกต่างระหว่างรหัสสแกน (เช่น WeChat) ระหว่างลูกค้าของคุณและลูกค้าอื่น ๆ
ตัวอย่างเช่นในธุรกิจคุณอาจต้องการทำสิ่งนี้ หากรหัส QR ของ บริษัท ของคุณถูกสแกนโดยแอพอื่น ๆ (เช่น WeChat) และคุณต้องการข้ามไปยังหน้าพรอมต์อาจมีลิงค์ดาวน์โหลดแอพในหน้าพรอมต์ และเมื่อมีการสแกนโดยแอพของคุณเองให้ทำคำขอที่เกี่ยวข้องโดยตรง
ในกรณีนี้สามารถทำได้ลิงก์ทั้งหมดในรหัส QR จะถูกเข้ารหัสในชั้นเดียวแล้วจัดการกับลิงค์อื่น
ตัวอย่างเช่น: www.test.com/qr?p=xxxxxx พารามิเตอร์ P ประกอบด้วยอัลกอริทึมการเข้ารหัสและการถอดรหัสที่ตกลงกันโดยเซิร์ฟเวอร์และไคลเอนต์ (สามารถสมมาตรหรือไม่สมมาตร) เมื่อสแกนรหัสบนเทอร์มินัลไปยังเส้นทางเฉพาะนี้พารามิเตอร์ P จะถูกใช้โดยตรงเพื่อแก้ไขพารามิเตอร์ P และรับ www.testqr.com/qrcode?key=s1arv เพื่อให้สามารถเริ่มร้องขอไปยังเซิร์ฟเวอร์ เนื่องจากลูกค้ารายอื่นไม่ทราบกฎนี้พวกเขาสามารถขอ www.test.com/qr?p=xxxxxx ได้โดยตรงเท่านั้น คำขอนี้กลับไปที่หน้าพรอมต์
วิธีทำให้รหัส QR ง่ายขึ้น
หลายครั้งที่ม้าถูกขอให้วิ่งและไม่กินหญ้า ฉันต้องการให้รหัส QR มีพารามิเตอร์มากมาย แต่ฉันไม่ต้องการให้รหัส QR ซับซ้อนเกินไปและเป็นการยากที่จะสแกนรหัส ในเวลานี้คุณต้องพิจารณาวิธีทำให้รหัส QR ง่ายขึ้นโดยไม่ส่งผลกระทบต่อธุรกิจ
รหัสตัวอย่าง
สร้างรหัส QR (ถอดขอบสีขาวและเพิ่มโลโก้กลาง)
ต้องนำเข้าแพ็คเกจ JAR: Core-2.0.jar ของ ZXING
นำเข้า java.awt.basicstroke; นำเข้า java.awt.color; นำเข้า java.awt.graphics; นำเข้า java.awt.graphics2d; นำเข้า java.awt.image; นำเข้า java.awt.shape; java.io.ByTeArrayOutputStream; นำเข้า java.io.fileOutputStream; นำเข้า java.io.ioException; นำเข้า java.util.hashmap นำเข้า java.util.map นำเข้า javax.imageio.imageio; com.google.zxing.multiformatwriter; นำเข้า com.google.zxing.common.bitmatrix; นำเข้า com.google.zxing.qrcode.decoder.errorcorrectionlevel; private static final int white = color.white.getrgb (); INT คงที่ส่วนตัวสุดท้ายเริ่มต้น _QR_SIZE = 183; สตริงสุดท้ายคงที่ส่วนตัว default_qr_format = "png"; ไบต์สุดท้ายคงที่สุดท้าย [] empty_bytes = ไบต์ใหม่ [0]; Public Static Byte [] CreateQrCode (เนื้อหาสตริง, ขนาด int, ส่วนขยายสตริง) {return createQrCode (เนื้อหา, ขนาด, ส่วนขยาย, null); } / *** สร้างรหัส QR ด้วยรูปภาพ* @param ข้อมูลเนื้อหาที่จะรวมอยู่ในรหัส QR* ขนาดขนาด @param* @param ส่วนขยายรูปแบบไฟล์ส่วนขยาย* @param insertimg ภาพโลโก้กลาง* @return* / ไบต์คงที่ (" + size +") ไม่สามารถเป็น <= 0 "); } byteArrayOutputStream baos = null; ลอง {map <encodeHintType, Object> hints = new HashMap <ENCODEHINTTYPE, Object> (); คำแนะนำ (encodeHintType.character_set, "UTF-8"); Hints.put (encodeHintType.error_Correction, ErrorCorrectionLevel.m); // ใช้ข้อมูลเพื่อสร้าง DOT เมทริกซ์ของขนาดที่ระบุ Bitmatrix M = ใหม่ MultiformatWriter (). ENCODE (เนื้อหา, BARCODEFORMAT.QR_CODE, ขนาด, ขนาด, คำแนะนำ); // ลบขอบสีขาว m = updatebit (m, 0); ความกว้าง int = m.getWidth (); ความสูง int = m.getheight (); // ตั้งค่าข้อมูลเป็น bitmatrix เป็น bufferDimage เพื่อสร้างภาพบัฟเฟอร์ภาพสีดำและสีขาวภาพ = bufferedImage ใหม่ (ความกว้าง, ความสูง, bufferedImage.type_int_rgb); สำหรับ (int i = 0; i <width; i ++) {สำหรับ (int j = 0; j <ความสูง; j ++) {image.setrgb (i, j, m.get (i, j)? สีดำ: สีขาว); }} if (insertimg! = null) {// แทรกการแทรกภาพโลโก้กลาง (ภาพ, insertimg, m.getWidth ()); } // ขยายภาพที่มีขนาดเล็กลงเนื่องจากการลบภาพขอบสีขาว = zoominimage (ภาพขนาดขนาด); BAOS = ใหม่ byteArrayOutputStream (); Imageio.write (รูปภาพ, ส่วนขยาย, baos); กลับ baos.tobytearray (); } catch (exception e) {} ในที่สุด {ถ้า (baos! = null) ลอง {baos.close (); } catch (ioexception e) {// todo บล็อก catch block ที่สร้างอัตโนมัติ e.printstacktrace (); }} return empty_bytes; } / ** * รหัส QR ที่กำหนดเองความกว้างขอบสีขาว * @param matrix * @param margin * @return * / ส่วนตัว bitmatrix updatebit (bitmatrix matrix, margin int) {int tempm = margin * 2; int [] rec = matrix.getenclosingRectAngle (); // รับแอตทริบิวต์ของรูปแบบรหัส QR int reswidth = rec [2] + tempm; int resheight = rec [3] + tempm; bitmatrix resmatrix = ใหม่ bitmatrix (reswidth, resheight); // สร้าง bitmatrix ใหม่ resmatrix.clear () ตามเส้นขอบที่กำหนดเอง; สำหรับ (int i = margin; i <reswidth - margin; i ++) {// loop เพื่อวาดรูปแบบรหัส QR ลงใน bitmatrix ใหม่สำหรับ (int j = margin; j <resheight - margin; j ++) {ถ้า (matrix.get (i - margin+rec [0] }} ส่งคืน resmatrix; } // ภาพซูมเข้าและออก public bufferedImage zoominimage (bufferedImage OriginalImage, ความกว้าง int, ความสูง int) {bufferedImage newImage = ใหม่ bufferedImage (ความกว้าง, ความสูง, originalImage.getType ()); กราฟิก g = newImage.getGraphics (); G.Drawimage (OriginalImage, 0, 0, ความกว้าง, ความสูง, null); G.Dispose (); คืนนิวเมจ; } private static void insertimage (bufferedImage source, image insertimg, ขนาด int) {ลอง {int width = insertimg.getWidth (null); ความสูง int = insertimg.getheight (null); ความกว้าง = ความกว้าง> ขนาด / 6? ขนาด / 6: ความกว้าง; // ตั้งค่าโลโก้เป็นหนึ่งในหกของขนาดของความสูงของรหัส QR = ความสูง> ขนาด / 6? ขนาด / 6: ความสูง; graphics2d graph = source.createGraphics (); int x = (ขนาด - ความกว้าง) / 2; int y = (ขนาด - ความสูง) / 2; graph.drawimage (insertimg, x, y, ความกว้าง, ความสูง, null); รูปร่างรูปร่าง = ใหม่ RoundRectangle2d.float (x, y, ความกว้าง, ความกว้าง, 6, 6); graph.setstroke (basicstroke ใหม่ (3f)); graph.draw (รูปร่าง); graph.dispose (); } catch (exception e) {e.printstacktrace (); }} ไบต์คงที่สาธารณะ [] createqrCode (เนื้อหาสตริง) {return createqrCode (เนื้อหา, default_qr_size, default_qr_format); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ลอง {fileOutputStream fos = ใหม่ fileOutputStream ("ab.png"); fos.write (createqrcode ("ทดสอบ")); fos.close (); } catch (exception e) {// todo บล็อก catch block ที่สร้างอัตโนมัติ e.printstacktrace (); -สร้างลิงก์สั้น ๆ
แนวคิดพื้นฐาน:
ทฤษฎีอัลกอริทึมการทำแผนที่ URL สั้น ๆ :
1. ใช้อัลกอริทึม MD5 เพื่อสร้างสตริงลายเซ็น 32 บิตแบ่งออกเป็น 4 ส่วนแต่ละส่วนมี 8 อักขระ
2. สำหรับ 4 ส่วนเหล่านี้ใช้เวลา 8 อักขระในแต่ละเซ็กเมนต์ปฏิบัติต่อมันเป็นบิตและการทำงานของสตริงเลขฐานสิบหกและ 0x3ffffffff (30 บิต 1) และไม่สนใจการประมวลผลมากกว่า 30 บิต
3. หาร 30 หลักที่ได้รับในแต่ละเซ็กเมนต์เป็น 6 ส่วนและแต่ละหมายเลข 5 หลักจะใช้เป็นดัชนีของตัวอักษรเพื่อรับอักขระเฉพาะและรับสตริง 6 บิตในทางกลับกัน
4. สตริง MD5 ดังกล่าวสามารถรับสตริง 6 บิต 4 บิตได้และสามารถใช้เป็นที่อยู่ URL สั้น ๆ ของ URL ที่มีความยาวนี้ได้
5. เป็นการดีที่สุดที่จะใช้ฐานข้อมูลคีย์-ค่าเพื่อจัดเก็บ ในกรณีของการชนให้แทนที่หนึ่ง หากการชนกันทั้งสี่ครั้งให้สร้าง MD5 ใหม่ (เนื่องจากมีตัวเลขสุ่มจะสร้าง MD5 ที่แตกต่างกัน)
คลาสสาธารณะ shorturlutil { / ** * ส่งผ่านในค่า 32 บิต md5 * @param md5 * @return * / สตริงคงที่สาธารณะ [] shorturl (สตริง md5) {// เพื่อใช้อักขระที่สร้าง url string [] chars = สตริงใหม่ [] {",", "c", " "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "V", "W", "X", "Y", "Z", "0" "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "q", "r", "s", "t", สตริง [] resurl = สตริงใหม่ [4]; สำหรับ (int i = 0; i <4; i ++) {// ใส่อักขระที่เข้ารหัสเป็น 8 บิตเป็นชุดของ hexadecimal และ 0x3ffffffffffff และดำเนินการบิตและการคำนวณ หากมากกว่า 30 บิตถูกละเว้นสตริง stempsubstring = md5.substring (i * 8, i * 8 + 8); // คุณต้องใช้ประเภทยาวเพื่อแปลงที่นี่เนื่องจาก Inteper .parseInt () สามารถประมวลผลได้ 31 บิตเท่านั้นและบิตแรกคือบิตสัญญาณ หากคุณใช้เวลาไม่นานมันจะอยู่นอกขอบเขต lhexlong ยาว = 0x3fffffff & long.parselong (stempsubstring, 16); สตริง outchars = ""; สำหรับ (int j = 0; j <6; j ++) {// สร้างค่าที่ได้รับด้วย 0x000003D บิตและการทำงานเพื่อรับอาร์เรย์อักขระดัชนีดัชนียาวดัชนี = 0x0000003d & lhexlong; // เพิ่มอักขระที่ได้รับ outchars += chars [(int) ดัชนี]; // แต่ละลูปถูกเลื่อนไปทางขวาโดย 5 บิต lhexlong = lhexlong >> 5; } // บันทึกสตริงลงในอาร์เรย์เอาต์พุตของดัชนีที่สอดคล้องกัน resurl [i] = outchars; } return resurl; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {String [] test = shorturl ("fdf8d941f23680be79af83f921b107ac"); สำหรับ (สตริงสตริง: ทดสอบ) {system.out.println (สตริง); - หมายเหตุ: รหัสหลักไม่ใช่ต้นฉบับและยืมมาจากรหัสของคนอื่นขอบคุณ!
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น