初投稿です。質問失礼します。
###概要
・GolangとReactでcookieを使った認証機能(ログイン・新規登録)の実装(cookieをGoで保存)
・chorme検証ツールのNetWorkの login/ にはcookieの値が出力されている。
・chorme設定から「全てのcookieを表示」の欄にはcookieが保存されていない(エラーは出ていない)。つまりcookieがきちんと書き込まれておらず、読み込みができない。
・現在の実行環境はReactがローカル、GoはGAE上本番環境。(Reactの本番環境でも同様の現象)
歴史
歴史番号とコードを関連付けました。
Golang
・echoのcontextでログイン機能実装とcookieの設定(ログイン自体は200 OK、cookieの書き込みのみできていない)...1
・echoでルーティングを設定し、ルーティング内にCORS設定を追加**...2**
React
・Axiosを利用して外部APIとの通信、ログインボタンの作成(POSTメソッド)...3
・先日タイトルと全く同様の問題が発生したため、ReactのCORS設定を見直したら直ったが、コードを触っているうちにまたcookieが保存されなくなる。...4
・現在AWS のS3とcloudfrontを使ってデプロイしているが今回ローカルでも問題が発生しているので関係はないと思われるためcookieの設定はしていない。
ソースコード
1
1//user_controller.go 2//echoのcontext 3func Login(c Context) error { 4 //formのuser 5 var formUser domain.User 6 if err := c.Bind(&formUser); err != nil { 7 return err 8 } 9 //取ってくるuser 10 var u domain.User 11 u, err := database.LoginUser(formUser) 12 if err != nil { 13 return err 14 } 15 WriteCookie(c, u.UUID) 16 return c.JSON(http.StatusOK, u) 17} 18 19 20 21//user_repository.go 22func LoginUser(formUser domain.User) (domain.User, error) { 23 var u domain.User 24 var err error 25 //email一致のuserを返す 26 res := db.First(&u, "email = ?", formUser.Email) 27 err = res.Error 28 if res.RecordNotFound() { 29 fmt.Println("-----------------") 30 fmt.Println("ユーザーが存在しません。") 31 return u, err 32 } 33 if err != nil { 34 fmt.Println("-----------------") 35 fmt.Println("予期せぬエラーです。") 36 return u, err 37 } 38 //passwordが一致するか(第一引数ハッシュ後password, 第二引数formのハッシュ化前password) 39 err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(formUser.Password)) 40 if err != nil { 41 fmt.Println("-----------------") 42 fmt.Println("パスワードが違います。") 43 return u, err 44 } 45 if err := db.First(&u).Related(&u.Follows, "Follows").Related(&u.Followers, "Followers").Related(&u.Reviews, "Reviews").Error; err != nil { 46 return u, err 47 } 48 return u, nil 49} 50 51//cookie.go 52func WriteCookie(c Context, uuid string) { 53 cookie := new(http.Cookie) 54 cookie.Name = data 55 cookie.Value = uuid 56 cookie.Path = "/" 57 cookie.Expires = time.Now().Add(24 * time.Hour) 58 cookie.Secure = true 59 cookie.HttpOnly = true 60 cookie.SameSite = http.SameSiteLaxMode 61 c.SetCookie(cookie) 62}
2
1//infra/router.go 2func CreateMux() *echo.Echo { 3 e := echo.New() 4 e.Validator = NewValidator() 5 // CORS設定 6 e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 7 AllowOrigins: []string{"http://app.ahiboh.com.s3-website-ap-northeast-1.amazonaws.com", "http://d32v7mjl1zna31.cloudfront.net", "http://localhost:3000"}, 8 AllowHeaders: []string{echo.HeaderAccept, echo.HeaderContentType, echo.HeaderOrigin, echo.HeaderCookie, echo.HeaderSetCookie, echo.HeaderAccessControlAllowOrigin, "*"}, 9 AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete, http.MethodPatch, http.MethodPut}, 10 AllowCredentials: true, 11 })) 12 //ローカルならlog表示 13 if !appengine.IsAppEngine() { 14 e.Use(middleware.Recover()) 15 e.Use(middleware.Logger()) 16 e.Use(middleware.Gzip()) 17 e.Static("/", "public") 18 } 19 return e 20} 21 22func Router(e *echo.Echo) { 23 e.POST("/signup/", func(c echo.Context) error { return controllers.Signup(c) }) 24 e.POST("/login/", func(c echo.Context) error { return controllers.Login(c) }) 25 e.DELETE("/logout", func(c echo.Context) error { return controllers.Logout(c) }) 26 e.GET("/cuser", func(c echo.Context) error { return controllers.CurrentUserGet(c) }) 27 e.GET("/user", func(c echo.Context) error { return controllers.UserGet(c) }) 28 e.GET("/users", func(c echo.Context) error { return controllers.UsersGet(c) }) 29 e.POST("/review/", func(c echo.Context) error { return controllers.ReviewPost(c) }) 30 e.GET("/reviews", func(c echo.Context) error { return controllers.ReviewsGet(c) }) 31 e.POST("/follow/", func(c echo.Context) error { return controllers.FollowPost(c) }) 32 e.DELETE("/follow", func(c echo.Context) error { return controllers.FollowDelete(c) }) 33 e.GET("/follows", func(c echo.Context) error { return controllers.FollowsGet(c) }) 34 e.GET("/test", func(c echo.Context) error { return test(c) }) 35} 36 37//server.go 38func init() { 39 var e = infra.CreateMux() 40 infra.Router(e) 41 //全ての通信をechoで行う設定 42 http.Handle("/", e) 43} 44
以下React, Login/index.tsx
3
1export const useLogin = () => { 2 const ini: formStruct = { 3 name: "", 4 email: "", 5 password: "" 6 } 7 const [state, setState] = useState(ini) 8 const { getCuser } = useCuser() 9 const [redirect, setRedirect] = useState(<></>) 10//ログインボタンを押すとloginUser発火 11 const loginUser = (email: string, password: string) => { 12 getCuser( 13 //ここで通信している 14 Axios.post('https://gratio-ahiboh-0222.appspot.com/login/', { 15 email: email, 16 password: password, 17 }) 18 ) 19 setState(ini) 20 setRedirect(<Redirect to="/" />) 21 } 22 return {state, setState, loginUser, redirect} 23} 24 25 const getCuser = useCallback(async (axios: any) => { 26 setLoading(true) 27 try { 28 const result = await axios 29 const res: UserType = result.data 30 setLoading(false) 31 dispatch({type: USERSET, result: res}) 32 } catch (e) { 33 setLoading(false) 34 setError(e.message) 35 } 36 }, [loading, error, sess] )
index.tsx (Reactのルートディレクトリ)
4
1Axios.defaults.withCredentials = true
仮説
・1週間ほど前まで同様のGo/GAE本番環境 + Reactの開発環境で動いていた(コードは少し変えました)ので、原因がいまいち掴めておりません。
・個人的にはGolangよりReactの方が怪しいと思っております(API通信自体はうまくいっている、最近はGoよりもReactのコードを書き換えた)
・しかし実際にできていないのは1のSetCookieの部分なのでなんとも言えません。変更点は強いて言うなら2のCORSのAllowOrigin部分です。
・React側はAxiosのグローバル設定のみで動いているのですが、React側でcookieだけブロックされている(?)のかな、とも考えています。もしくはAxiosの書き方の問題?
・本当にエラーも出ずcookieが書き込まれないだけとなっております。
###検証
・デバッグではfmtを使ってWriteCookieメソッドまでたどり着いていることは確認されました。
・ダメもとでAllowOriginsを* (全て許可)に設定しましたが治らず。
・cookieのSecure, HTTPOnly, SameSite属性はあってもなくても治りませんでした。
・Axiosの記述をtry catchではなくpromiseパターンとしてthen-catchで記述しましたが治りませんでした。
補足情報
・Mac OS Catalina
・VSCode
・Golang (https://gratio-ahiboh-0222.appspot.com/)
Echo
・React (http://localhost:3000/)
Axios
・CORSはこちら等を参考にしました。
https://qiita.com/att55/items/2154a8aad8bf1409db2b
回答1件
あなたの回答
tips
プレビュー