<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                跨域指的是瀏覽器不能執行其他網站或域名下的腳本。之所以形成跨域,是因為瀏覽器的同源策略造成的,是瀏覽器對javascript程序做的安全限制,現在所有支持JavaScript 的瀏覽器都會使用這個策略。 在實際應用中會遇到需要跨域的場景,比如前后端分離,前后端不在同域(這里的同域指的是同一協議,同一域名,同一端口),那么,它們之間相互通信如何解決呢? 跨域解決有以下幾種方法: ### jsonp跨域 這里jsonp跨域其實是利用iframe、img、srcipt,link標簽的src或href屬性來實現的,這些標簽都可以發送一個get請求資源,src 和href 并沒有受同源策略的限制。 這里我們拿懶人教程示例 ```go <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JSONP 實例</title> <script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script> </head> <body> <div id="divCustomers"></div> <script> $.getJSON("https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=?", function(data) { var html = '<ul>'; for(var i = 0; i < data.length; i++) { html += '<li>' + data[i] + '</li>'; } html += '</ul>'; $('#divCustomers').html(html); }); </script> </body> </html> ``` jsonp主要站在前端的角度去解決問題,這種方式有一定的局限性,就是僅適用get請求。 ### nginx代理跨域 #### nginx配置解決iconfont跨域 眾所周知js、css、img等常用資源不受瀏覽器同源策略限制,但一些特殊資源如iconfont字體文件(`eot|otf|ttf|woff|svg`)除外,這里通過修改nginx配置就可以解決。 ```go location / { add_header Access-Control-Allow-Origin *; } ``` #### nginx 反向代理 同源策略是瀏覽器的安全策略,不屬于http協議一部分,限制的是js腳本。而服務器端調用的http接口,不受同源策略限制,也不存在跨域問題。 實現思路:nginx服務器作為中間代理(或跳轉機),實現從域名A訪問域名B,像訪問同域一樣。 示例 ```go server { listen 80; server_name http://domain1; location / { proxy_pass http://domain2:8081/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; } } ``` ### nodejs 代理 nodejs實現原理和nginx基本類似。 修改app.js ```js var express = require('express'); const proxy = require('http-proxy-middleware'); const app = express(); app.set('port', '809'); app.all('*', function (req, res, next) { // 解決跨域問題 res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); if (req.method == "OPTIONS") { res.send(200); } else { next(); } }); var options = { target: 'http://localhost:8090', changeOrigin: true, }; var exampleProxy = proxy(options); app.use('/', exampleProxy); app.listen(app.get('port'), () => { console.log(`server running @${app.get('port')}`); }); ``` 如是vue+nodejs環境 通過只修改vue.config.js,不用修改nodejs也可以實現代理跨域。 ```js devServer: { host: '0.0.0.0', port: 8080, disableHostCheck: true, proxy: { '/*': { target: 'https://www.runoob.com', secure: false, changeOrigin: true } } } ``` ### cors 跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。 比如,站點 http://domain-a.com 的某 HTML 頁面通過 的 src 請求 http://domain-b.com/image.jpg。 網絡上的許多頁面都會加載來自不同域的CSS樣式表,圖像和腳本等資源。 出于安全原因,瀏覽器限制從腳本內發起的跨源HTTP請求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非響應報文包含了正確CORS響應頭。 前面扯了很多方法,其實歸根結底是圍繞cors機制來實現(除了nginx反向代理)的,具體就是服務端發送 Access-Control-Allow-Origin 以及相關響應頭,來通知瀏覽器有權訪問資源。 前面講了 nodejs 或nginx服務器端通過設置Access-Control-Allow-Origin,可以實現跨域,這里講一下golang實現方式,當然php、java等也可以實現、原理相同。 示例1 ```go package main import ( "net/http" ) funccors(f http.HandlerFunc)http.HandlerFunc { returnfunc(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") // 允許訪問所有域,可以換成具體url,注意僅具體url才能帶cookie信息 w.Header().Add("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") //header的類型 w.Header().Add("Access-Control-Allow-Credentials", "true") //設置為true,允許ajax異步請求帶cookie信息 w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") //允許請求方法 w.Header().Set("content-type", "application/json;charset=UTF-8") //返回數據格式是jsonif r.Method == "OPTIONS" { w.WriteHeader(http.StatusNoContent) return } f(w, r) } } funcindex(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello Golang")) } funcmain() { http.HandleFunc("/", cors(index)) http.ListenAndServe(":8000", nil) } ``` 示例 2 gin 框架跨域中間件 ```go package main import ( "github.com/gin-gonic/gin""net/http" ) funcmain() { r := gin.Default() r.Use(Cors())//默認跨域 r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run(":8090") } funcCors() gin.HandlerFunc { returnfunc(c *gin.Context) { method := c.Request.Method origin := c.Request.Header.Get("Origin") if origin != "" { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization") c.Header("Access-Control-Allow-Credentials", "true") c.Set("content-type", "application/json") } //放行所有OPTIONS方法if method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) } c.Next() } } ``` gin有個官方的跨域中間件 https://github.com/gin-contrib/cors **注意**: 某些簡單請求不會觸發[CORS 預檢請求](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Preflighted_requests "CORS 預檢請求") 。 Content-Type 的值僅限于下列三者之一: + text/plain + multipart/form-data + application/x-www-form-urlencoded 默認 現在應用中越來越多前端和服務端都采用json通訊,如vue等。 要求前端Content-Type設置為 application/json,且是post請求,這屬于復雜請求,將觸發CORS 預檢請求。即瀏覽器會先發送一次options請求,同意后才繼續發送post請求。 當發送這種請求時,在瀏覽器的network會發現兩條請求。同時在服務端接收前端參數時需要注意,以前通過get 、post方法會失效。 具體接收參數方法,php語言為 file_get_contents('php://input') 。 ###golang語言 net/http ```go package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) func cors(f http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") // 允許訪問所有域,可以換成具體url,注意僅具體url才能帶cookie信息 w.Header().Add("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") //header的類型 w.Header().Add("Access-Control-Allow-Credentials", "true") //設置為true,允許ajax異步請求帶cookie信息 w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") //允許請求方法 w.Header().Set("content-type", "application/json;charset=UTF-8") //返回數據格式是json if r.Method == "OPTIONS" { w.WriteHeader(http.StatusNoContent) return } f(w, r) } } type User struct { Username string `json:"username"` Password string `json:"password"` } func index(w http.ResponseWriter, r *http.Request) { body, _ := ioutil.ReadAll(r.Body) fmt.Println(string(body)) var user User if err := json.Unmarshal(body, &user); err == nil { fmt.Println(user) } else { fmt.Println(err) } w.Write([]byte("Hello Golang")) } func main() { http.HandleFunc("/", cors(index)) http.ListenAndServe(":8000", nil) } ``` gin 框架 對于gin框架我們就需要bind來解決這個問題 示例 ```go type User struct { Username string `form:"username" json:"username" binding:"required"` Password string `form:"password" json:"password" binding:"required"` } func Login(c *gin.Context) { var u User err :=c.BindJSON(&u) fmt.Println(err) fmt.Println(u) } ``` 先建一個結構體user,再使用BindJSON綁定,將request中的Body中的數據按照JSON格式解析到User結構體中。 需要注意: + binding:"required" 字段對應的參數未必傳沒有會拋出錯誤,非banding的字段,對于客戶端沒有傳,User結構會用零值填充。對于User結構沒有的參數,會自動被忽略。 + 結構體字段類型和所傳參數類型要一致。 Bind的實現都在gin/binding里面. 這些內置的Bind都實現了Binding接口, 主要是Bind()函數. + context.BindJSON() 支持MIME為application/json的解析 + context.BindXML() 支持MIME為application/xml的解析 + context.BindYAML() 支持MIME為application/x-yaml的解析 + context.BindQuery() 只支持QueryString的解析, 和Query()函數一樣 + context.BindUri() 只支持路由變量的解析 + Context.Bind() 支持所有的類型的解析, 這個函數盡量還是少用(當QueryString, PostForm, 路由變量在一塊同時使用時會產生意想不到的效果), 目前測試Bind不支持路由變量的解析, Bind()函數的解析比較復雜, 這部分代碼后面再看 + 通常在解決跨域問題時,通過在服務端設置head請求的方式比較便利。 + 跨域需要帶cookie信息,則必須滿足服務端 設置"Access-Control-Allow-Origin"為固定url,且Access-Control-Allow-Credentials: true,前端js 也要設置withCredentials: true + 前端Content-Type設置為 application/json時,服務端在接收參數數據方式不同。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看