คำแนะนำฉบับสมบูรณ์เกี่ยวกับการตั้งค่าพร็อกซีใน Angular สำหรับการเรียก API หลังพร็อกซีขององค์กรหรือด้วยการรับรองความถูกต้องของ Windows
นักพัฒนาเชิงมุมใช้ Angular CLI เพื่อการพัฒนาท้องถิ่น ความต้องการที่พบบ่อยที่สุดประการหนึ่งคือการตั้งค่าพร็อกซีในสภาพแวดล้อม dev ภายในเครื่องเพื่อหลีกเลี่ยงข้อผิดพลาด CORS เมื่อแอป Angular ส่งคำขอ HTTP ไปยัง API ที่อยู่ในโดเมนอื่น Angular CLI ทำให้กระบวนการค่อนข้างง่าย แต่อาจยุ่งยากในบางกรณี
ในบทความนี้ ฉันจะพูดถึงวิธีตั้งค่าพร็อกซีเซิร์ฟเวอร์ dev
- พร็อกซีเป็น API ใน localhost
- พร็อกซีไปยัง API ภายนอกภายในเครือข่ายองค์กร
- พร็อกซีเป็น API โดยใช้การรับรองความถูกต้องของ Windows (IIS)
- m โครงร่างหลายรูปแบบในส่วนหัว WWW-Authenticate หนึ่งอัน
ตั้งค่าพร็อกซีเพื่อเชื่อมต่อกับ API ใน localhost
ด้วย Angular CLI เราสามารถเริ่มเซิร์ฟเวอร์ dev ภายในเครื่องได้โดยใช้คำสั่งด้านล่าง
ng serve
คำสั่งเรียกใช้เซิร์ฟเวอร์ dev ภายในตาม "เซิร์ฟเวอร์ webpack dev" ตามค่าเริ่มต้น เซิร์ฟเวอร์ dev จะทำงานบน http://localhost:4200
เมื่อแอป Angular ต้องการเรียก API แบ็กเอนด์ซึ่งโฮสต์อยู่ในเครื่องที่ http://localhost:3000,
เราจะพบข้อผิดพลาด CORS เนื่องจากการเรียก HTTP ใช้ต้นทางอื่น (localhost:3000
)
this.http.get('http://locahost:3000/api/') .subscribe(res => {...});
ปัญหา CORS สามารถแก้ไขได้ด้วยการกำหนดค่าพร็อกซีเซิร์ฟเวอร์ Angular dev คุณสามารถสร้างการกำหนดค่าพร็อกซีตัวอย่างได้ที่ด้านล่าง
// proxy.conf.json { "/api": { "target": "http://localhost:3000", "secure": false, } } // we change the angular http call to remove the domain prefix this.http.get('/api/') .subscribe(res => {...});
ดังที่แสดงในแผนภาพต่อไปนี้ พร็อกซีจะอยู่ระหว่างแอป Angular และ API แบ็กเอนด์ และแปลการเรียก “api/v1
” เป็น API แบ็กเอนด์ ข้อผิดพลาด CORS จะไม่เกิดขึ้นเนื่องจากการเรียกไปยัง API มีต้นกำเนิดเดียวกัน (localhost:4200/api
) ในขณะนี้
เพื่อให้การกำหนดค่าพร็อกซีมีผล จะต้องส่งผ่านไปยังคำสั่ง ng serve
ng serve --proxy-config proxy.conf.json
หรือเราสามารถเพิ่มลงในการกำหนดค่า angular.json
ได้
"serve": { ... "options": { ... "proxyConfig": "proxy.conf.json" } }
เชื่อมต่อกับ API ภายนอกที่อยู่ด้านหลังพร็อกซีขององค์กร
บ่อยครั้งที่เราทำงานภายในเครือข่ายองค์กร และแอป Angular ในสภาพแวดล้อมการพัฒนาท้องถิ่นยังจำเป็นต้องเชื่อมต่อกับ API ภายนอกด้วย จากตัวอย่างก่อนหน้านี้ เราอาจจำเป็นต้องเรียก "http://abc.company.com/api" ในแอป Angular แทนที่จะเรียก "http://localhost:3000/api"
การเข้าถึง API ภายนอกหลังพร็อกซีของบริษัทจำเป็นต้องกำหนดค่าตัวแปรสภาพแวดล้อม HTTP_PROXY
และ HTTPS_PROXY
หากพร็อกซีใช้ใบรับรอง SSL จะต้องตั้งค่าสถานะ secure
เป็นเท็จ เพื่อข้ามการตรวจสอบใบรับรอง
ในการจัดการพร็อกซีขององค์กร เราต้องสร้าง proxy.conf.js
ตามด้านล่างนี้
const HttpsProxyAgent = require('https-proxy-agent'); const proxyConfig = [ { context: '/api', pathRewrite: { '^/api': '' }, target: 'https://api.abc.com', changeOrigin: true, secure: false } ]; function setupForCorporateProxy(proxyConfig) { const proxyServer = process.env.http_proxy || process.env.HTTP_PROXY; if (proxyServer) { const agent = new HttpsProxyAgent(proxyServer); proxyConfig.forEach(c => { c.agent = agent; }); } return proxyConfig; } module.exports = setupForCorporateProxy(proxyConfig);
ในตัวอย่างข้างต้น เราพร็อกซีคำขอ เช่น api/v1/client
ไปยังเซิร์ฟเวอร์ภายนอก https://api.abc.com/v1/client
เมื่อจำเป็นต้องใช้พร็อกซีขององค์กร เราจะตั้งค่าออบเจ็กต์ HTTPS agent ในพร็อกซีตามตัวแปรสภาพแวดล้อม HTTP_PROXY
และ HTTPS_PROXY
เพิ่มตัวเลือก secure:false
เพื่อจัดการใบรับรอง SSL แบบกำหนดเองในพร็อกซีขององค์กร
หากต้องการใช้การกำหนดค่า js ใหม่สำหรับแอป Angular ให้รันสิ่งต่อไปนี้
ng serve --proxy-config proxy.conf.js
เป็นที่น่าสังเกตว่ามีเอเจนต์สองประเภท: HttpsProxyAgent
และ HttpProxyAgent,
จำเป็นต้องเลือกเอเจนต์ที่เหมาะสมตามการตั้งค่าสภาพแวดล้อม
พร็อกซีเป็น API โดยใช้การรับรองความถูกต้องของ windows (IIS)
การรับรองความถูกต้องของ Windows ถูกใช้กันอย่างแพร่หลายในหลายๆ บริษัทที่พึ่งพาระบบนิเวศของ Microsoft สถานการณ์อาจเป็นเรื่องยุ่งยากหากแอป Angular เชื่อมต่อกับบริการ API ที่โฮสต์ด้วย IIS ซึ่งได้รับการป้องกันโดยการรับรองความถูกต้องของ Windows
ปัญหาทั่วไปคือการโทรจากแอป Angular ไปยัง API จะส่งกลับ 401 เมื่อใช้การตั้งค่าพร็อกซีในสภาพแวดล้อมการพัฒนาท้องถิ่น
ตัวอย่างเช่น /api/v1/../login
เป็นจุดสิ้นสุดที่ได้รับการปกป้องโดย Windows Authentication คำขอไปยัง API จาก Angular App ที่รันในเครื่องจะได้รับการตอบกลับที่ไม่ได้รับอนุญาต 401 รายการ ด้านล่างนี้คือภาพหน้าจอแท็บเครือข่ายในเครื่องมือนักพัฒนา Chrome
สาเหตุหลักของปัญหาคือการรับรองความถูกต้องของ Windows นั้นขึ้นอยู่กับการเชื่อมต่อ แต่พรอกซีตัดการเชื่อมต่อแบบ Keep-Live
ภายใต้ประทุนของการรับรองความถูกต้องของ windows จะใช้ Kerberos หรือ NTLM โปรโตคอลใดโปรโตคอลหนึ่งจะต้องมีการเชื่อมต่อแบบ Keep-Live เพื่อรักษาสถานะการรับรองความถูกต้อง
เมื่อเรียก /api/v1/../login
เบราว์เซอร์จะพยายามสร้างการเชื่อมต่อกับเซิร์ฟเวอร์ IIS ผ่านการจับมือเจรจา NTLM ซึ่งประกอบด้วย 3 ส่วน ได้แก่ข้อความ Type-1, Type-2 และข้อความ Type-3 ดูรายละเอียดเพิ่มเติมเกี่ยวกับการจับมือ NTLM ได้ "ที่นี่" คุณอาจสังเกตเห็นแล้วว่ามีการเรียก HTTP สองครั้งที่แสดงสำหรับคำขอเดียวกันในภาพหน้าจอด้านบน มันคือสองส่วนแรกของการจับมือกัน
เนื่องจากคำขอเป็นแบบพร็อกซีในเครื่อง ข้อความจับมือ 3 รายการจึงถูกส่งไปในคำขอ (ซ็อกเก็ต) 3 รายการแยกกันผ่านพร็อกซี ดังนั้นจึงไม่สามารถรักษาการเชื่อมต่อแบบ Keep-Live ไว้ในกระบวนการได้ นั่นคือสาเหตุที่ข้อความสุดท้ายไม่เกิดขึ้น
เพื่อแก้ไขปัญหา เราจำเป็นต้องกำหนดค่าพร็อกซีเพื่อรักษาการเชื่อมต่อเดียวระหว่างเบราว์เซอร์และเซิร์ฟเวอร์ IIS แพ็คเกจagentkeepalive
สามารถช่วยให้เราบรรลุเป้าหมายนี้ได้ การกำหนดค่าพร็อกซีที่อัปเดตแสดงอยู่ด้านล่าง
const Agent = require("agentkeepalive"); const keepaliveAgent = new Agent({ maxSockets: 1, keepAlive: true, maxFreeSockets: 10, keepAliveMsecs: 1000, timeout: 60000, keepAliveTimeout: 30000 // free socket keepalive for 30 seconds }); const PROXY_CONFIG = [ { target: "http://localhost:3000", context: "/api", secure: false, changeOrigin: true, loglevel: "debug", agent: keepaliveAgent } ]; module.exports = PROXY_CONFIG;
การกำหนดค่าพร็อกซีที่อัปเดตจะตั้งค่าสถานะ maxSockets
เป็น 1, keepAlive
เป็นจริง และตั้งค่าการหมดเวลาเป็น 30 วินาที ซึ่งนานพอที่จะทำให้การจับมือเสร็จสมบูรณ์ การกำหนดค่านี้มีจุดมุ่งหมายเพื่อให้ http.Agent
รักษาการเชื่อมต่อแบบต่อเนื่องระหว่างเบราว์เซอร์และเซิร์ฟเวอร์ IIS ผ่านทางพร็อกซีในกระบวนการตรวจสอบสิทธิ์
ตอนนี้คำขอ /api/v1/../login
API ควรใช้งานได้
ด้านบนคือบันทึกแท็บเครือข่ายหลังจากการตรวจสอบความถูกต้องด้วยการกำหนดค่าใหม่สำเร็จ เราจะเห็นคำขอทั้งสามในระหว่างการแฮนด์เชค และคำขอสุดท้ายส่งคืนสถานะความสำเร็จของ HTTP 200
หลายรูปแบบในส่วนหัว WWW-Authenticate เดียว
สาเหตุที่เป็นไปได้อีกประการหนึ่งของข้อผิดพลาดจากการรับรองความถูกต้องของ Windows คือส่วนหัว www-authenticate
ตาม RFC 7235 การมีรูปแบบการรับรองความถูกต้องหลายรูปแบบในฟิลด์ส่วนหัว www-authenticate
เดียวเป็นเรื่องปกติ แม้ว่าจะทำให้แยกวิเคราะห์ฟิลด์ได้ยากก็ตาม
เจ้าหน้าที่จะต้องใช้ความระมัดระวังเป็นพิเศษในการแยกวิเคราะห์ค่าฟิลด์ส่วนหัว WWW-
Authenticate หรือ Proxy-Authenticate หากมี
มากกว่าหนึ่งความท้าทาย หรือหากมีฟิลด์ WWW-Authenticate header
มากกว่าหนึ่งรายการ มีให้ เนื่องจากเนื้อหาของการท้าทายอาจมี
มีรายการพารามิเตอร์การตรวจสอบสิทธิ์ที่คั่นด้วยเครื่องหมายจุลภาค
ความจริงก็คือการรองรับเบราว์เซอร์นั้น น่าสงสัย ด้านล่างนี้เป็นตัวอย่างของส่วนหัว www-authenticate ที่มี 2 รูปแบบ
WWW-Authenticate: Negotiate, NTLM
เบราว์เซอร์บางตัวอาจไม่สามารถแยกวิเคราะห์ข้างต้นได้อย่างถูกต้อง และจะทำให้กระบวนการจับมือ NTLM หยุดทำงาน เพื่อแก้ไขปัญหานี้ เราสามารถใช้การโทรกลับ proxyRes
ใน http-proxy-middleware
ดังต่อไปนี้
const onProxyRes = function (proxyRes, req, res) { var key = 'www-authenticate'; proxyRes.headers[key] = proxyRes.headers[key] && proxyRes.headers[key].split(','); }; // add it into the proxy config option onProxyRes: onProxyRes
การกำหนดค่าพร็อกซีแบบเต็มมีลักษณะดังนี้
const Agent = require("agentkeepalive"); const keepaliveAgent = new Agent({ maxSockets: 1, keepAlive: true, maxFreeSockets: 10, keepAliveMsecs: 1000, timeout: 60000, keepAliveTimeout: 30000 // free socket keepalive for 30 seconds }); const onProxyRes = function (proxyRes, req, res) { var key = 'www-authenticate'; proxyRes.headers[key] = proxyRes.headers[key] && proxyRes.headers[key].split(','); }; const PROXY_CONFIG = [ { target: "http://localhost:3000", context: "/api", secure: false, changeOrigin: true, onProxyRes: onProxyRes, agent: keepaliveAgent } ]; module.exports = PROXY_CONFIG;
ด้วยการเพิ่มการโทรกลับใหม่ รูปแบบต่างๆ ในส่วนหัว www-authenticate
จะถูกส่งไปหลายบรรทัด และการจับมือเจรจา NTLM จะสามารถดำเนินการต่อได้
// From the original response header www-authenticate: Negotiate, NTLM // After the onProxRes callback function www-authenticate: ['Negotiate', 'NTLM'] // It is equivalent to < WWW-Authenticate: Negotiate < WWW-Authenticate: NTLM
สรุป
ในบทความนี้ เราจะพูดถึงวิธีหลีกเลี่ยงปัญหา CORS ด้วยการตั้งค่าพร็อกซีโดยใช้ Angular CLI เพื่อการพัฒนาในเครื่อง ฉันหวังว่ามันจะมีประโยชน์สำหรับคุณ หากคุณกำลังใช้งาน Angular ด้านหลังพร็อกซีขององค์กร และ/หรือใช้ IIS พร้อมการรับรองความถูกต้องของ Windows
ขอให้มีความสุขในการเขียนโปรแกรม!
เนื้อหาเพิ่มเติมได้ที่ PlainEnglish.io.
ลงทะเบียนเพื่อรับ จดหมายข่าวรายสัปดาห์ฟรี ของเรา ติดตามเราบน Twitter, LinkedIn, YouTube และ Discord .
สนใจที่จะขยายขนาดการเริ่มต้นซอฟต์แวร์ของคุณหรือไม่ ลองดูที่ วงจร