目錄
前言
一、驗證碼與登錄
二、使用步驟
1.先apipost測試一波
2.先搞驗證碼
3.跨域問題
4.后端走起
總結
前言
近期要做一個比較完整的demo,需要自己做一個前端登錄頁面,不過api接口都是現成的,一開始以為過程會很easy,但是由于跨域問題、后端代理、驗證碼關聯登問題,還是小小折騰一些,正好將過程記錄下。
一、驗證碼與登錄
現代網站為了系統的安全性以及降低惡意攻擊,一般都會在用戶名、密碼驗證的基礎上,增加驗證碼驗證。
這里主要就涉及驗證碼關聯問題,即怎么讓后端知道后端生成的驗證碼就是對應我前端輸入的驗證碼?以下我們就來一步步講解。包括驗證碼、cookie、登錄邏輯登
二、使用步驟
1.先apipost測試一波
通過apipost先把涉及的兩個接口調用通了,然后再寫代碼。
測試發現,調用這兩個接口的時候,都給傳遞同一個cookie即可成功登錄。
那么,我寫代碼的時候,也生成一個cookie,給這兩個接口傳遞同一個cookie應該就可以了。
2.先搞驗證碼
<div class="mb-6"><label for="captcha" class="block text-gray-700 text-sm font-bold mb-2">驗證碼</label><div class="flex gap-2"><input type="text" id="captcha" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" required><img id="captchaImage" alt="驗證碼" class="h-10 cursor-pointer" onclick="refreshCaptcha()"></div>
</div><script>// 刷新驗證碼async function refreshCaptcha() {const captchaImage = document.getElementById('captchaImage');const url = `http://xx.com/api/captcha?t=${Date.now()}`;captchaImage.src = url;}// 頁面加載時刷新驗證碼window.onload = refreshCaptcha;</script>
3.跨域問題
由于原有接口的安全性設置,進行了CORS跨域設置,導致前端無法直接請求。
另外,出于安全考慮,前端也無法手動給后端傳遞cookie,正常過程是后端給前端返回cookie,然后后續調用后端接口會自動傳遞當前域下的cookie。
這里通過apipost工具、后端寫代碼都沒問題,主要是對瀏覽器請求做了限制,準確說是瀏覽器的一種安全機制。
在不能調整原有接口的CORS設置的情況,那就只能自己寫后端代理接口,那么關鍵就是讓后端可以成功調用,那么問題基本就解決了。
4.后端走起
后端實現生成驗證碼是很順利,但是在登錄邏輯這里發現前面說的“給這兩個接口傳遞相同的cookie”的假設無法成功登錄。
再次F12看原系統登錄請求,發現獲取驗證碼的接口會返回cookie,然后登錄的時候傳遞了這個cookie。之前一直沒注意到,是當前問AI的時候,AI跟我說的是獲取驗證碼會通過Set_Cookie返回cookie,實際直接就是cookie,而且還不是每次請求都會返回,可能本地有了就不返回?
按照最新思路,重新調整邏輯:
1)獲取驗證碼,獲取到cookie;設置到前端
2)登錄邏輯,自動傳遞到后端,后端再把這個cookie傳遞給實際登錄接口。
ok搞定。
@app.get("/captcha")
async def get_captcha(request: Request):target_url = f"{KAPTCHA_URL}?t={int(time.time()*1000)}"try:resp = requests.get(target_url, stream=True)cookie_val= resp.cookies["cookie_key"]response = StreamingResponse(resp.iter_content(chunk_size=64), media_type=resp.headers["Content-Type"])# 開發環境臨時禁用Secureresponse.set_cookie(key="cookie_key",value=cookie_val,httponly=True,samesite="Lax", # 開發環境使用Laxsecure=False, # 開發環境禁用Securepath="/",)return responseexcept Exception as e:return JSONResponse(content={"error": str(e)}, status_code=500)@app.post("/user/login")
async def proxy_login(request: Request):# 獲取 form-dataform_data = await request.form()# 單獨獲取某個字段login_id = form_data.get("loginId")password = form_data.get("password")kaptcha_code = form_data.get("kaptchaCode")cookies = request.cookiescookie_val = cookies.get("cookie_key")try:response = login(login_id, password, kaptcha_code, cookie_val)return JSONResponse(content=response.json(), status_code=response.status_code)except requests.RequestException as e:return JSONResponse(content={"errCode": ErrCode.FAILURE.value,"errMsg": str(e),"data": {}},status_code=500,)
總結
以上就是今天要講的內容,本文主要介紹了自己寫前端集成已有驗證碼、登錄接口過程中遇到的問題以及如何解決,希望可以幫助到大家。
本文重點總結:
1)前端安全性考慮,前端無法跨域訪問后端接口,無法直接給后端傳遞cookie。調用后端接口的時候,會默認把當前域下cookie傳遞到后端
2)驗證碼與登錄邏輯,驗證碼接口會返回一個cookie,調用登錄接口的時候傳遞這個cookie,實現前后端同一個驗證碼的關聯驗證