iT邦幫忙

0

Vuejs 使用LineLogin發生Access to XMLHTTPRequest Cross問題

  • 分享至 

  • xImage

按照這篇https://ithelp.ithome.com.tw/articles/10217768 大大的文章,
https://www.youtube.com/watch?v=D6429DPxGC8 (yt影片連結)
下載他提供的專案在localhost:8080是可以正常運行的,但是套到自己的專案時就會跑出下面的錯誤,無法正常的使用axios call line官方給的api
Access to XMLHttpRequest at 'https://api.line.me/oauth2/v2.1/token' from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

因專案的性質無法公開,想請有解的大神們可否跟我聯絡
klgt13145220@gmail.com
或是指點解決的方向,為了這個問題,爬很久的文都無解orz

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

1
Han
iT邦研究生 1 級 ‧ 2021-03-15 18:16:12

可參考Line官方提供的流程圖,取token的動作應該是要在你的後端應用呼叫token api
在前端呼叫會因為同源政策的關係,導致無法呼叫不同domain的api

詳細資訊可參考 Line官方文件

流程圖

看更多先前的回應...收起先前的回應...

但按照您的說法,我參考的文章也是在localhost的domain下去呼叫,也應該要無法呼叫對吧?
但為什麼他的做法可以正常取得各項資訊呢?

klgt13145220你是用AJAX,影片的不是

https://www.youtube.com/watch?v=D6429DPxGC8
這才是我參照的影片拍勢
他是用postman和jwt去測試
我是用vuejs進行開發的,按照他影片內的作法跟著做的
他的教法確實是用axios(就是ajax)吧?

klgt13145220 依照影片中的流程,他會是先開一個登入line視窗,人工點了登入後才跳到用axios呼叫的頁面,你也是這樣的流程嗎?

是的,有確實導向登入畫面,也有出現我在line devloper那邊設定的應用程式請求需求,但就是會噴出跨域的錯誤,以至於我無法取得accesstoken跟使用者資訊
作法是在env新增環境變數
寫入要call的專案的line ID,以及專案ID
以及登入後重新導向的uri
在components內的LineLogin.vue使用$emit將click事件傳遞出去
在Navbar.vue的methods內loginEvent這個function將希望line回傳的參數一個一個拼起來,並導向登入畫面
Navbar.vue :
mounted的這個鉤子下去call(post) Line官方提供的api

1
koro_michael
iT邦新手 2 級 ‧ 2021-03-16 18:16:42

花時間運行了你的程式碼,發現其中一個問題是你在打 api 的時候沒有把 code 帶過去

https://ithelp.ithome.com.tw/upload/images/20210316/20135412g5dIac09Lz.png

也就是說 Navbar.vue 中的 404 行的 code: this.query.code, 取到的是 undefined

目前最快的解決方法就是把 Router 模式改為 mode: 'history'

剩下的晚點再繼續 debug

=============================================================

暫時解決的方法: 多加一個代理伺服器設定

把以下設定加入到 vue.config.js (你原本專案就有一個設定,加在他的下方)

'/line': {
    target: 'https://api.line.me',
    changeOrigin: true,
    pathRewrite: {
        '^/line': 'https://api.line.me'
    }
}

之後 axios 那邊改寫成

axios.post('/line/oauth2/v2.1/token',

https://ithelp.ithome.com.tw/upload/images/20210317/201354123QYjk79ykI.png

推斷為新舊版本問題的差異,有待查證,上面的方法就先用著吧

看更多先前的回應...收起先前的回應...

目前改成history cross錯誤還是存在
會是跟我在vue.config.js寫了proxy代理有關嗎?
後端開給我的api我在localhost這邊無法call且噴了跨域的錯誤才寫的

我知道錯誤還是在,所以有空要繼續 debug

好的,感謝您QQ

klgt13145220幫你弄了一個暫時的方法,試試看

淺水員 iT邦大師 6 級 ‧ 2021-03-17 12:09:15 檢舉

CORS 的問題透過代理是正確的
這是瀏覽器 AJAX 的限制

另外,Line 給的 client_secret 原本就不應該送到前端
這也是需要伺服器代理的理由

淺水員
但好玩的一點是,如果是使用這一個範例專案

https://github.com/r3850355/line_login_demo

不用設定什麼東西,也不會出現跨域問題,正在比對原因到底是出在哪邊

感謝你! 找解法找到快崩潰了orz
已經可以正常取得accesstoken了,另外問一個小問題
若是我要上傳到公司的server上我vue.config.js第一個代理的target
是不是就要改成正式站上對應的domian
之前在線上課程直接串接資料就好,沒想到就職後會遇到跨域這種奇怪的問題,若要跟後端順利配合是不是proxy代理這段還要去充實相關的常識

對,我也很疑惑,他根本沒有寫代理,比對很久也看不出個所以然
菜雞心態炸裂中

klgt13145220很遺憾,那邊的設定只對開發時有效,之後用戶運行環境是不會有代理伺服器的

淺水員 iT邦大師 6 級 ‧ 2021-03-17 15:39:37 檢舉

klgt13145220 你只負責前端頁面嗎?
如果我做一個範例,後端語言你習慣用什麼?
因為正常流程官網這樣寫
所以有些東西原本是後端要處理的。

我只負責前端資料串接,
會這樣寫是因老闆指示要我去接第三方登入讓user在前台用第三方登入
我(前端)取得他們(user)的social id跟email,再傳到後端讓他處理
後端是php,但後端的詳情我不太清楚

淺水員 iT邦大師 6 級 ‧ 2021-03-17 21:19:30 檢舉

正常狀況下,有些是後端完成的,範例

如果都交給前端處理,那麼 CHANNEL_SECRET 會暴露在前端,會不會有安全性的問題再跟老闆討論吧。(可搭配官網的流程圖)

這邊附上純前端處理的範例(單純兩個頁面不使用任何框架)

PS. 我測試時他都有給 Access-Control-Allow-Origin: *,所以沒跨域的問題。

真的非常感謝您還給我範例可以參考
另外想問個問題,
問題點是我原本在localhost(本地這端)要call公司老闆給的api
使用axios這個套件去call api
老闆的api的domian是https://app.wundoo.com.tw/
我local這邊的協定是http不是https且domian是localhost
所以我直接call api時理所當然的會噴出跨域請求的error
上網找解法是需要在跟目錄底下的vue.config.js
這個設定檔內,寫入proxy代理相關的設定
即可在本地端call 跨域的api
但現在問題上當我丟到公司的server上面
api會有404的錯誤,經檢查network過後看到前面的domain
變成http://anbon.works
導致我的錯誤變成 => api的url是不對的
代表我proxy代理如同你上述所說,在server會失效
我將其中一隻call ajax的function api設定成直接call對應的url
https://app.wundoo.com.tw/api/xxxx
在server上就又會噴出跨域錯誤

淺水員 iT邦大師 6 級 ‧ 2021-03-18 22:49:43 檢舉

前端開發測試時遇到跨域的問題分為兩種狀況

  1. 這個頁面最後會跟API同網域。
  2. 這個頁面最後跟API不同網域。

如果是第一種狀況除了使用代理外,其實也可以改瀏覽器設定或是裝cors anywhere 這類的瀏覽器插件。當然這些方法都只是開發時測試使用,正式上線時因為同網域,所以不會有跨域的問題。

如果是第二種狀況,只能請後端送 Access-Control-Allow-Origin header(雖然這邊用代理也可以,但還是要後端提供代理的API)

您好為了使用FB第三方登入時,將redirect uri設定為https://localhost:8080
https://ithelp.ithome.com.tw/articles/10230052 =>是根據此篇的教學轉換的,將localhost的協定轉成"https",
結果line的問題又浮現出來,在console的錯誤變成bad request 404
不確定問題是否跟轉協定有關
新專案連結: https://github.com/andrew-HuangHaoChe/ask
昨天熬夜到三點將google和FB取得id、profile的部分搞定,
看到line又炸掉心真的很累orz,可以再勞煩您為我解惑嗎

klgt13145220https://ithelp.ithome.com.tw/upload/images/20210319/20135412b02fDzqRfW.png

這邊有沒有也跟著變 https?

Line登入後跳轉回來的網址長這樣

https://localhost:8080/?code=XLIzm1Btyng9iJWG7IUN&state=dev123456#/
console.log(this.query.code)

變成 undefined ,所以 Line 判你 400 錯誤

解決方法: 改成以下寫法

const urlParams = new URLSearchParams(window.location.search)
    const options = Qs.stringify({ // POST的參數  用Qs是要轉成form-urlencoded 因為LINE不吃JSON格式
      grant_type: 'authorization_code',
      code: urlParams.get('code'),
      redirect_uri: process.env.VUE_APP_LINE_REDIRECT_URL,
      client_id: process.env.VUE_APP_LINE_CHANELL_ID,
      client_secret: process.env.VUE_APP_LINE_CHANELL_SECRET
    })

可以了,感謝(跪)

淺水員大大,想問一下你範例裡面的code

//recive.html
fetch(url, {
    method: 'post',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: paramStr
}).then(r=>{
    if(r.status!==200) {
        throw r.statusText;
    }
    return r.json();
}).then(json=>{
    document.querySelector('#log').textContent=JSON.stringify(json, null, 4);
});

裡面的return r.json();,我在.json()之前console出來的r裡面找不到回應的物件,但是為何轉為json物件之後就跑出來了,請問這是什麼原理?

我要發表回答

立即登入回答