Permintaan normal
Baru -baru ini, yang lain perlu memanggil fungsi sistem kami, dan pihak lain berharap dapat menyediakan API sehingga dapat memperbarui data. Karena teman sekelas ini adalah pengembang klien, ia memiliki kode yang mirip dengan yang berikut.
@RequestMapping (Method = RequestMethod.post, value = "/Update.json", menghasilkan = mediatype.application_json_value) public @responseBody contacter update (@RequestBody contacterro) {Logger.debug ("Dapatkan Permintaan Pembaruan {}", contacterro.tostro (logger) ("dapatkan permintaan pembaruan {}", contacterro.toStracter (logger ("get update {}", contacterro. {contacterro.setusername ("adminupdate-wangdachui");} return contacterro;}Klien memulai permintaan HTTP melalui kode untuk memanggilnya. Kemudian, siswa bertanya: Dia berharap untuk menggunakan panggilan JS melalui browser, jadi ada masalah lintas domain.
Mengapa domain silang
Sederhananya, browser membatasi akses ke kode JS di bawah Situs A untuk membuat permintaan AJAX ke URL di bawah Situs B. Jika nama domain saat ini adalah www.abc.com, maka kode JS yang berjalan di lingkungan saat ini tidak dapat mengakses sumber daya di bawah nama domain www.zzz.com untuk alasan keamanan.
Misalnya: Kode berikut dapat digunakan untuk memanggil antarmuka secara normal melalui kode JS di bawah nama domain ini
(function () {var url = "http: // localhost: 8080/API/home/update.json"; var data = {"userId": 123, "username": "wangdachui"}; $. Ajax ({URL: URL, anyage: 'post', datypype: 'json' dATA: $. 'Application/json'}). Done (function (hasil) {console.log ("Success"); console.log (hasil);}). fail (function () {console.log ("error");})}) ()Outputnya adalah:
Objek {userid: 123, nama pengguna: "adminupdate-wangdachui"}Namun, mengakses dengan nama domain lain akan menyebabkan kesalahan:
Opsi http: // localhost: 8080/API/home/update.jsonxmlHttpRequest tidak dapat memuat http: // localhost: 8080/API/home/update.json. Tanggapan untuk Permintaan Preflight Tidak Lulus Cek Kontrol Akses: Tidak ada header Access-Control-Wallow-Origin 'hadir pada sumber daya yang diminta. Oleh karena itu 'NULL' karena itu tidak diizinkan akses. Responsnya memiliki kode status HTTP 403.
Larutan
Jsonp
Menggunakan JSONP untuk melakukan domain silang adalah cara yang relatif umum, tetapi ketika antarmuka telah ditulis, baik server dan sisi panggilan perlu diubah dan kompatibel dengan antarmuka asli, yang agak terlalu banyak pekerjaan, jadi kami mempertimbangkan metode lain.
Protokol CORS
Menurut Referensi: Setiap halaman perlu mengembalikan header HTTP bernama 'Access-Control-Allow-Origin' untuk memungkinkan akses ke situs di domain asing. Anda hanya dapat mengekspos sumber daya yang terbatas dan akses situs yang terbatas di luar domain. Dalam mode COR, tanggung jawab kontrol akses dapat ditempatkan di tangan pengembang halaman, bukan administrator server. Tentu saja, pengembang halaman perlu menulis kode pemrosesan khusus untuk memungkinkan akses ke dunia luar. Kami dapat memahaminya sebagai: jika suatu permintaan perlu mengizinkan akses lintas domain, Anda perlu mengatur akses-kontrol-kontrol-asal di header HTTP untuk memutuskan situs mana yang diizinkan untuk mengakses. Jika Anda perlu mengizinkan permintaan dari www.foo.com ke cross-domain, Anda dapat mengatur: access-control-allow-origin: http://www.foo.com. Atau Access-Control-Allow-Origin: *. CORS didukung di sebagian besar browser modern sebagai bagian dari HTML5.
CORS memiliki header umum berikut
Access-Control-Allow-Origin: http://foo.orgAccess-Control-Max-Age: 3628800Access-Control-Allow-Methods: GET, PUT, DELETEAccess-Control-Allow-Headers: content-type "Access-Control-Allow-Origin" indicates that it allows "http://foo.org" to initiate cross-domain permintaan. "Access-Control-Max-Age" menunjukkan bahwa dalam 3628800 detik, tidak diperlukan permintaan pra-cek. Hasil "Methods-Methods-Methods-Methods" menunjukkan bahwa hal itu memungkinkan Get, put, hapus permintaan out-domain "akses-kontrol-header" menunjukkan bahwa hal itu memungkinkan permintaan lintas domain untuk menyertakan header tipe konten "
Proses CORS dasar
Pertama, permintaan preflight dikeluarkan, yang pertama mengeluarkan metode opsi dan permintaan yang berisi header "asal" ke server sumber daya. Balasan ini dapat mengontrol metode permintaan COR, header HTTP, dan informasi verifikasi. Permintaan domain asing nyata hanya akan dimulai setelah permintaan diizinkan.
Spring MVC mendukung CORS
Tanggapan untuk Permintaan Preflight Tidak Lulus Cek Kontrol Akses: Tidak ada header Access-Control-Wallow-Origin 'hadir pada sumber daya yang diminta. Oleh karena itu 'NULL' karena itu tidak diizinkan akses. Responsnya memiliki kode status HTTP 403.
Dari pesan kesalahan di atas, kita dapat melihat bahwa alasan langsung adalah bahwa tidak ada header origin akses-kontrol-awal di header permintaan. Jadi ide langsung kami adalah menambahkan header ini ke header permintaan. Server dapat mengembalikan 403, menunjukkan bahwa server memang telah memproses permintaan.
MVC Interceptor
Pertama, kami mengkonfigurasi pencegat untuk mencegat permintaan dan mencatat informasi header permintaan.
DEBUG requestURL:/api/Home/update.json DEBUG method:OPTIONS DEBUG header host:localhost:8080 DEBUG header connection: keep-alive DEBUG header cache-control:max-age=0 DEBUG header access-control-request-method:POST DEBUG header origin:null DEBUG header user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 DEBUG header access-control-request-headers:accept, content-type DEBUG header accept:*/* DEBUG header accept-encoding:gzip, deflate, sdch DEBUG header penerimaan-bahasa: ZH-CN, ZH; q = 0,8, en; q = 0,6
Mencetak login Posthandle menemukan bahwa status responsnya adalah 403 saat ini. Melacak kode SpringMVC menemukan bahwa di org.springframework.web.servlet.dispatcherServlet.dodispatch, handleRexecutionChain akan diperoleh berdasarkan permintaan. Setelah SpringMVC memperoleh prosesor reguler, ia akan memeriksa apakah itu permintaan lintas domain. Jika demikian, itu akan menggantikan instance asli.
@Overridepublic final handleRexecutionChain getHandler (permintaan httpservletrequest) melempar pengecualian {objek handler = getHandlerinternal (request); if (handler == null) {handler = getDefaulthandler (); if handler = handler == null) {return null; handlerName = (string) handler; handler = getApplicationContext (). getBean (handlerName);} handleRexecutionChain executionChain = getHandLerExecutionChain (handler, request); if (corsutils.iscorsruest (request)) {corsconfiguration globalconfig = corsutils.iscorsReQu this.corsConfigSource.getCorsConfiguration(request);CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);executionChain = getCorsHandlerExecutionChain(request, executionChain, config);} return executionChain;}Metode pemeriksaan juga sangat sederhana, yaitu, periksa apakah ada bidang asal di header permintaan.
public static boolean iScorsRequest (permintaan httpservletrequest) {return (request.getheader (httpheaders.origin)! = null);}Permintaan kemudian akan diserahkan ke httpRequestHandlerapter.handle untuk diproses, dan logika yang berbeda akan diproses sesuai dengan pegangan. Penilaian sebelumnya didasarkan pada header permintaan sebagai permintaan domain silang. Handler yang diperoleh adalah PreflightHandler, yang diimplementasikan sebagai:
@Overridepublic void handleRequest (permintaan httpservletRequest, respons httpservletResponse) melempar ioException {corsprocessor.processRequest (this.config, permintaan, respons);}Lanjutkan untuk menindaklanjuti
@Overridepublic Boolean ProcessRequest (CorsConfiguration Config, httpservletRequest, httpservletResponse response) melempar ioException {if (! Corsutils.iscorsrequest (request)) {return true;} servletserverHerSponsponseSeRSESE (return = servletserverHresponseSeSponse (return = servletserverSpronSeSeRSESE (return = servletServerHresponseSee (return = servletServerSponseSponSe (return = servletServerSponseRponse (return true; ServletserverHttpresponse (respons); servletserverhttpRequest serverRequest = baru servletserverhttpRequest (permintaan); if (Webutils.issameorigin (serverRequest)) {Logger.debug ("Skip Cors Processing, permintaan adalah hal yang sama-berasal"); return true;} if (responseHascor preflightrequest = corsutils.ispreflightrequest (request); if (config == null) {if (preflightrequest) {rejectrequest (serverResponse); return false;} else {return true;} return handleInternal (serverrequest, serveResponse, configLighTrighTrighrMetode ini pertama-tama memeriksa apakah itu permintaan lintas domain, dan jika tidak, itu akan kembali secara langsung. Kemudian periksa apakah itu di bawah domain yang sama, atau apakah ia memiliki bidang akses-kontrol-awal-origin di header respons atau apakah ia memiliki metode akses-kontrol-request dalam permintaan. Jika kondisi penilaian dipenuhi, permintaan ditolak.
Dari sini kita tahu bahwa cek dapat dilewati dengan mengatur header origin-control-control-origin dari respons sebelum cek. Kami menangani Prehandle di Interceptor. Tambahkan kode berikut:
response.setHeader ("Access-Control-Allow-Origin", "*");Pada saat ini, permintaan opsi di browser mengembalikan 200. Tetapi masih ada kesalahan:
Tipe Konten Bidang Header Permintaan tidak diizinkan oleh header akses-kontrol-terkendali dalam respons preflight.
Kami memperhatikan bahwa ada akses-pengendalian-pengendalian-header: menerima, tipe konten di header permintaan, tetapi header permintaan ini tidak. Pada saat ini, browser tidak mengirim permintaan sesuai kebutuhan. Coba tambahkan responsnya:
response.setHeader ("akses-kontrol-allow-headers", "asal, X-requested-with, tipe konten, terima");Eksekusi Sukses: Object {UserId: 123, Username: "Adminupdate-Wangdachui"}.
Sejauh ini: Kami menggunakan prinsip analisis untuk memungkinkan SpringMVC mencapai domain lintas, tanpa perubahan apa pun pada implementasi asli dan kode klien.
SpringMVC 4
Selanjutnya, dalam referensi 2, SpringMVC4 menyediakan metode yang sangat nyaman untuk mengimplementasikan domain silang.
Gunakan anotasi dalam permintaan permintaan. @Crossorigin (origins = "http: // localhost: 9000")
Implementasi Global. Definisi Kelas Warisan WebMVCConfigurerAdapter
Kelas Publik CorsConfigurerAdapter memperluas webmvcconfigurerAdapter {@Overridepublic void addCorsmappings (Corsregistry Registry) {Registry.addmapping ("/API/*").Menyuntikkan kelas ke dalam wadah:
<Bean> </bean>
Meringkaskan
Di atas adalah semua penjelasan terperinci tentang implementasi pegas dan pemrosesan kode permintaan lintas domain. Saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!