欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3中使用Supabase?Auth方法詳解

 更新時間:2022年07月04日 11:11:16   作者:前端小工  
這篇文章主要為大家介紹了Vue3中使用Supabase?Auth方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

Supabase是一個自稱的 "開源Firebase替代品"。我對與Supbase合作已經(jīng)有一段時間了,我想我將嘗試使用他們的認證API來為Vue.js 3應(yīng)用程序進行認證設(shè)置。

首先,你為什么要使用Supabase Auth?最重要的是,如果你使用Supabase作為你的數(shù)據(jù)存儲,(它有一些非常甜蜜的好處),Supabase Auth是你可以管理對這些數(shù)據(jù)的訪問的唯一方法。其次,雖然Supabase Auth也有許多不同的功能。

  • 沒有中間件的用戶權(quán)限(通過Postgres的行級安全)。
  • 神奇的電子郵件鏈接
  • 社交提供者的登錄
  • 以及所有其他你期望的封裝在一個簡單的JavaScript SDK中的Auth功能

綜上所述,值得一提的是,Supabase Auth不是一個獨立的認證提供商,它只是為了與其他Supabase服務(wù)(數(shù)據(jù)、存儲等)一起使用。

好了,讓我們開始在我們的Vue.js 3應(yīng)用程序中實施Supabase Auth。

安裝Supabase

我假設(shè)你已經(jīng)有了一個用Vue Router設(shè)置的Vue.js 3應(yīng)用程序,如果沒有,你可以下載這個模板代碼來進行操作。我還假設(shè)你已經(jīng)有了一個Supabase賬戶和項目設(shè)置。如果沒有,你可以前往supabase.io,它將引導你完成第一步。

然后,為了與Supabase auth以及它的任何其他服務(wù)合作,我們需要安裝Supabase JavaScript SDK。

npm install @supabase/supabase-js

設(shè)置Supabase

安裝完Supabase后,我們需要經(jīng)過幾個步驟來設(shè)置它。我將創(chuàng)建一個名為UseSupabase.js 的組合,用來組織這個設(shè)置。

// UseSupabase.js
import { createClient } from "@supabase/supabase-js";
// these can come from an environment variable if desired
// not required however as they are 100% exposed on the client side anyway 
// and that's ok, Supabase expects this (security is provided by Row Level Security)
const supabaseUrl = "";
const supabaseKey = "";
// setup client
const supabase = createClient(supabaseUrl, supabaseKey);
// expose supabase client
export default function useSupabase() {
  return { supabase };
}

supabaseUrl和supabaseKey可以在Supabase儀表板上的Settings > API 。

當你在Supabase界面時,你也可以到Autentication > Settings ,設(shè)置你的網(wǎng)站網(wǎng)址,以便Supabase知道如何正確地重定向確認郵件等。它的默認值是localhost:3000,但你可以根據(jù)需要進行修改。

創(chuàng)建一個AuthUser組合

設(shè)置好Supabase SDK后,我們現(xiàn)在可以開始使用它了。首先,我將創(chuàng)建一個AuthUser組合,以抽象出與AuthUser的一些交互,并存留所有我們需要填寫的方法。這在我們將來想脫離Supabase時很有幫助,并幫助我們把所有的AuthUser功能集中到一個地方。

import { ref } from "vue";
// user is set outside of the useAuthUser function
// so that it will act as global state and always refer to a single user
const user = ref(null);
export default function useAuthUser() {
  /**
   * Login with email and password
   */
  const login = async ({ email, password }) => {};
  /**
   * Login with google, github, etc
   */
  const loginWithSocialProvider = (provider) => {};
  /**
   * Logout
   */
  const logout = async () => {};
  /**
   * Check if the user is logged in or not
   */
  const isLoggedIn = () => {};
  /**
   * Register
   */
  const register = async ({ email, password, ...meta }) => {};
  /**
   * Update user email, password, or meta data
   */
  const update = async (data) => {};
  /**
   * Send user an email to reset their password
   * (ie. support "Forgot Password?")
   */
  const sendPasswordRestEmail = async (email) => {};
  return {
    user,
    login,
    loginWithSocialProvider,
    isLoggedIn,
    logout,
    register,
    update,
    sendPasswordRestEmail,
    maybeHandleEmailConfirmation,
  };
}

創(chuàng)建頁面

接下來,讓我們來創(chuàng)建典型用戶認證流程所需的頁面。我使用Tailwind CSS做了一些樣式設(shè)計,但可以根據(jù)你的需要自由調(diào)整這些樣式。

注冊.vue

我們需要的第一個頁面是一個注冊頁面。它需要包含必要的字段,以便在Supabase中創(chuàng)建一個用戶。這些字段是電子郵件和密碼。我們也可以在Supabase中為我們的用戶添加任意的元數(shù)據(jù),這意味著我們也可以讓用戶的真實姓名成為注冊的一部分。

// Register.vue
<script>...</script>
<template>
  <form class="max-w-lg m-auto" @submit.prevent="handleSubmit">
    <h1 class="text-3xl mb-5">Register</h1>
    <label>Name <input v-model="form.name" type="text" /></label>
    <label>Email <input v-model="form.email" type="email" /></label>
    <label>Password <input v-model="form.password" type="password" /></label>
    <button>Register</button>
  </form>
</template>

在腳本部分,我們可以使用一個反應(yīng)式引用來跟上表單的數(shù)據(jù),同時提供一個函數(shù)來處理表單的提交。在表單提交時,我們將從AuthUser組合中調(diào)用注冊函數(shù)(它仍然是空的,但我們將在稍后用supabase的具體調(diào)用來填充它),然后重定向到一個頁面,指示用戶檢查他們的電子郵件以確認注冊。

// Register.vue
<script setup>
import { ref } from "vue";
import useAuthUser from "@/composables/UseAuthUser";
import { useRouter } from "vue-router";
// Use necessary composables
const router = useRouter();
const { register } = useAuthUser();
// Form reactive ref to keep up with the form data
const form = ref({
  name: "",
  email: "",
  password: "",
});
// function to hand the form submit
const handleSubmit = async () => {
  try {
        // use the register method from the AuthUser composable
    await register(form.value);
        // and redirect to a EmailConfirmation page the will instruct
        // the user to confirm they're email address
    router.push({
      name: "EmailConfirmation",
      query: { email: form.value.email },
    });
  } catch (error) {
    alert(error.message);
  }
};
</script>
<template>...</template>

最后,我們需要為該頁面注冊路由。

// router/index.js
const routes = [
  //...
    {
    name: "Register",
    path: "/register",
    component: () => import("@/pages/Register.vue"),
  },
]

如果你使用了模板代碼,訪問/register ,應(yīng)該會得到一個看起來像這樣的頁面。

EmailConfirmation.vue

既然我們在注冊后重定向到一個EmailConfirmation頁面,我們當然需要讓它存在。它將只是一個簡單的模板和一條信息。當我們在上面重定向時,我們也提供了來自注冊表單的電子郵件作為一個查詢變量,所以我們可以在這里顯示它。

<template>
  <div>
    <h1 class="text-3xl">Thanks for registering!</h1>
    <p>
      Please confirm your email to finishing registering:
      {{ $route.query.email }}
    </p>
  </div>
</template>

再一次,我們也需要注冊這個路由。

// router/index.js
const routes = [
    //...
    {
    name: "EmailConfirmation",
    path: "/email-confirmation",
    component: () => import("@/pages/EmailConfirmation.vue"),
    },
]

現(xiàn)在訪問帶有電子郵件查詢變量的/email-confirmation 路由將看起來像這樣。

/[email protected]

登錄.vu

在注冊并確認了他們的電子郵件后,用戶將不得不登錄。讓我們接下來創(chuàng)建這個頁面。

該模板將包括一個帶有電子郵件和密碼字段的表單,以及一個指向忘記密碼頁面的鏈接,還有一個處理Github登錄的鏈接。

<script>...</script>
<template>
  <div class="max-w-lg m-auto">
    <form @submit.prevent="handleLogin">
      <h1 class="text-3xl mb-5">Login</h1>
      <label>Email <input v-model="form.email" type="email" /></label>
      <label>Password <input v-model="form.password" type="password" /></label>
      <button>Login</button>
      <router-link to="/forgotPassword">Forgot Password?</router-link>
    </form>
    <div class="mt-5">
      <a @click.prevent="handleLogin('github')">Github</a>
    </div>
  </div>
</template>

在腳本部分,我們可以創(chuàng)建一個反應(yīng)式引用來跟上表單的值,以及一個函數(shù)來處理表單的提交。

<script setup>
import { ref } from "vue";
import useAuthUser from "@/composables/UseAuthUser";
import { useRouter } from "vue-router";
// Use necessary composables
const router = useRouter();
const { login, loginWithSocialProvider } = useAuthUser();
// keep up with form data
const form = ref({
  email: "",
  password: "",
});
// call the proper login method from the AuthUser composable
// on the submit of the form
const handleLogin = async (provider) => {
  try {
    provider
      ? await loginWithSocialProvider(provider)
      : await login(form.value);
    router.push({ name: "Me" });
  } catch (error) {
    alert(error.message);
  }
};
</script>
<template>...</template>

注冊完路由后,你可以訪問/login 路由,看到一個漂亮的登錄表單。

// router/index.js
const routes = [
    //...
    {
    name: "Login",
    path: "/login",
    component: () => import("@/pages/Login.vue"),
  },
]

ForgotPassword.vue

由于我們在上面實現(xiàn)了一個忘記密碼的鏈接,讓我們也把這個頁面用腳手架搭出來。

在模板中,我們只需要一個帶有單個電子郵件字段的表單,以便收集我們應(yīng)該發(fā)送重置鏈接的電子郵件。

<script>...</script>
<template>
  <form class="max-w-lg m-auto" @submit.prevent="handlePasswordReset()">
    <h1 class="text-3xl mb-5">Forgot Password?</h1>
    <label>Email <input v-model="email" type="email" /></label>
    <button>Send Reset Email</button>
  </form>
</template>

在腳本部分,我們將創(chuàng)建一個電子郵件反應(yīng)式參考,以跟上表單中的電子郵件輸入,并定義一個函數(shù),在表單提交時調(diào)用AuthUser可組合的sendPasswordRestEmail 函數(shù)。

<script setup>
import useAuthUser from "@/composables/UseAuthUser";
import { ref } from "vue";
// use necessary composables
const { sendPasswordRestEmail } = useAuthUser();
// keep up with email
const email = ref("");
// function to call on submit of the form 
// triggers sending the reset email to the user
const handlePasswordReset = async () => {
  await sendPasswordRestEmail(email.value);
  alert(`Password reset email sent to: ${email.value}`);
};
</script>

最后,我們將注冊這個路由。

// router/index.js
const routes = [
    //...
    {
    name: "ForgotPassword",
    path: "/forgotPassword",
    component: () => import("@/pages/ForgotPassword.vue"),
  },
]

現(xiàn)在,點擊登錄頁面上的 "忘記密碼?"鏈接將把你帶到這里。

Me.vue

我們需要的最后一個頁面是一個個人資料頁面,在用戶登錄后顯示他們的秘密信息。我們將它稱為/me

// router/index.js
const routes = [
    //...
    {
    name: "Me",
    path: "/me",
    component: () => import("@/pages/Me.vue"),
  },
]

我們還將添加路由中間件,讓我們的程序知道這應(yīng)該是一個受保護的路由,只有通過認證的用戶才能訪問。

{
  name: "Me",
    meta: {
        requiresAuth: true,
    },
    //...
},

然后,為了讓這個中間件真正發(fā)揮作用,我們需要這樣來實現(xiàn)它。

const router = createRouter({
  history: createWebHistory(),
  routes,
});
router.beforeEach((to) => {
    // here we check it the user is logged in
    // if they aren't and the route requries auth we redirect to the login page
  const { isLoggedIn } = useAuthUser();
  if (!isLoggedIn() && to.meta.requiresAuth) {
    return { name: "Login" };
  }
});
export default router;

頁面本身將是一個簡單的問候用戶的信息。

<script setup>
import useAuthUser from "@/composables/UseAuthUser";
const { user } = useAuthUser();
</script>
<template>
  <div v-if="user">
        <!--user_metadata is the key supabase nests all arbitrary meta data under-->
    <div>Hello {{ user.user_metadata.name }}</div>
  </div>
</template>

我們現(xiàn)在還不會嘗試查看這個頁面,因為我們還沒有實現(xiàn)登錄。

https://github.com/danielkellyio/supabase-auth-example

現(xiàn)在,頁面和AuthUser組合已經(jīng)到位,我們可以開始通過調(diào)用Supabase SDK來填充AuthUser組合函數(shù)的內(nèi)容。

我們需要做的第一件事是訪問我們的Supabase客戶端。我們可以通過導入UseSupabase可組合函數(shù)并從中解構(gòu)Supabase客戶端來做到這一點。

import useSupabase from "@/composables/UseSupabase";
export default function useAuthUser() {
    const { supabase } = useSupabase();
    //...
}

現(xiàn)在我們可以通過我們的空函數(shù),一個一個地填充它們。

login()

為了登錄Supabase,我們需要調(diào)用supabase.auth.signIn 。我們也可以等待響應(yīng),如果有錯誤就拋出一個新的錯誤,否則就返回登錄的用戶。

const login = async ({ email, password }) => {
    const { user, error } = await supabase.auth.signIn({ email, password });
    if (error) throw error;
    return user;
};

loginWithSocialProvider()

loginWithSocialProvider也同樣簡單。只需要將提供者傳遞給signIn方法。

const loginWithSocialProvider = async (token) => {
    const { user, error } = await supabase.auth.signIn({ provider });
    if (error) throw error;
    return user;
};

logout()

現(xiàn)在,為了注銷,我們需要調(diào)用Supabase的signOut方法。由于用戶不再可用,所以沒有什么可以從注銷中返回。

const logout = async () => {
  const { error } = await supabase.auth.signOut();
  if (error) throw error;
};

isLoggedIn()

對于isLoggedIn函數(shù),我們只需檢查reactive ref user是否有一個值。

const isLoggedIn = () => {
    return !!user.value;
};

如果你在想,我們在登錄用戶時從來沒有設(shè)置過這個值,你是完全正確的,但我們將利用另一個小的supabase方法來幫助我們解決這個問題,就在一分鐘之內(nèi)。

register()

register函數(shù)看起來幾乎和login函數(shù)一樣,接收電子郵件和密碼。然而,它也需要接受其他用戶信息(即元數(shù)據(jù))。另外,我們將重定向到個人資料頁面,并附上一些查詢變量,其中包含一些有用的信息。

const register = async ({ email, password, ...meta }) => {
  const { user, error } = await supabase.auth.signUp(
    { email, password },
    { 
            //arbitrary meta data is passed as the second argument under a data key
            // to the Supabase signUp method
            data: meta,
            // the to redirect to after the user confirms their email
            // window.location wouldn't be available if we were rendering server side
            // but since we're all on the client it will work fine
      redirectTo: `${window.location.origin}/me?fromEmail=registrationConfirmation"`,
        }
  );
  if (error) throw error;
  return user;
};

請注意這個很酷的小技巧,我們把meta:...meta 。這允許我們在調(diào)用函數(shù)時,在傳遞給函數(shù)的對象中提供同一層次的元數(shù)據(jù),但在函數(shù)中單獨訪問它。

// for example
register({email: '[email&nbsp;protected]', password: 'password123', name: 'Daniel Kelly', favoriteFood: 'Spaghetti'})
// meta will be {name: 'Daniel Kelly', favoriteFood: 'Spaghetti'}

update()

雖然我們實際上沒有提供更新用戶的接口,但我們可以去實現(xiàn)這個函數(shù),因為Supabase讓它變得如此簡單。

const update = async (data) => {
    const { user, error } = await supabase.auth.update(data);
    if (error) throw error;
    return user;
};

sendPasswordResetEmail()

最后一個要實現(xiàn)的函數(shù)是sendPasswordResetEmail 。再一次,supabase有一個簡單的解決方案。

const sendPasswordRestEmail = async (email) => {
    const { user, error } = await supabase.auth.api.resetPasswordForEmail(email);
    if (error) throw error;
    return user;
};

觀察Auth狀態(tài)的變化

在這一點上,我們幾乎已經(jīng)準備好開始使用我們的接口了,但還有一個關(guān)鍵步驟需要執(zhí)行。我們需要知道用戶何時登錄或注銷,并相應(yīng)地更新AuthUser組合中的反應(yīng)式ref。

你的第一個想法可能是在登錄和注銷方法中完成這個任務(wù),這在某些時候是可行的。然而,如果用戶因為會話過期而注銷了呢?或者如果用戶在Supabase那邊被更新或刪除了呢?在這兩種情況下,我們的登錄和注銷方法都不會被調(diào)用。

為了解決這個問題,Supabase提供了一個叫做onAuthStateChange 的函數(shù)。

我們可以在我們的supabase組合中調(diào)用這個函數(shù),讓它監(jiān)聽auth狀態(tài)的所有變化,然后相應(yīng)地設(shè)置我們的用戶reactive ref。

// UseSupabase.js
import { createClient } from "@supabase/supabase-js";
import useAuthUser from "@/composables/UseAuthUser";
// config
const supabaseUrl = "";
const supabaseKey = "";
// setup client
const supabase = createClient(supabaseUrl, supabaseKey);
// ? setup auth state listener ?
supabase.auth.onAuthStateChange((event, session) => {
    // the "event" is a string indicating what trigger the state change (ie. SIGN_IN, SIGN_OUT, etc)
    // the session contains info about the current session most importanly the user dat
  const { user } = useAuthUser();
    // if the user exists in the session we're logged in
    // and we can set our user reactive ref
  user.value = session?.user || null;
});
// expose supabase client
export default function useSupabase() {
  return { supabase };
}

我選擇在UseSupabase.js中的函數(shù)調(diào)用之外做這件事,這樣它就只被調(diào)用一次,并與其他Supabase設(shè)置代碼組織在一起。

測試東西

現(xiàn)在到了關(guān)鍵時刻。我們應(yīng)該有大部分的工作。(盡管你馬上就會看到,我們還需要再做一些調(diào)整)。在你的瀏覽器中導航到注冊頁面并注冊。

之后,你應(yīng)該成功地被重定向到EmailConfirmation頁面,你的電子郵件地址顯示在信息中。

另外,如果你檢查你的收件箱,你會像預(yù)期那樣收到電子郵件。

順便提一下,如果你想定制這封電子郵件的樣子,你可以在Supabase儀表板上的Authentication > Templates 。

另外,如果你在Authentication > Users ,你就可以看到你的新注冊用戶的狀態(tài)是:Waiting for Verication!

很好,現(xiàn)在去點擊電子郵件中的那個鏈接吧。哦,天哪!我們被重新定向到了一個新的網(wǎng)站。我們被重定向到了登錄頁面......這不對。然而,請注意,標題右上方的鏈接確實寫著 "注銷"

如果我們點擊到me 頁面,它將讓我們訪問它,并正確顯示我們在注冊表格中提供的名字。

問題是,在我們點擊頁面的那一瞬間,我們的中間件正在運行,我們還沒有完全登錄,因此authStateChange還沒有發(fā)生,還沒有設(shè)置我們的用戶反應(yīng)式。

讓我們在我們的中間件中做一個例外,如果查詢變量fromEmail存在,我們就繼續(xù)讓導航通過,因為我們知道,從確認郵件中來,用戶將立即登錄。

router.beforeEach((to) => {
  const { isLoggedIn } = useAuthUser();
  if (
    !isLoggedIn() &&
    to.meta.requiresAuth &&
    !Object.keys(to.query).includes("fromEmail")
  ) {
    return { name: "Login" };
  }
});

還要注意,這不是一個安全問題。如果有人在沒有登錄的情況下隨意在查詢字符串中包括fromEmail ,由于用戶不存在,反正什么都不會顯示出來,也不會從Supabase收到關(guān)于用戶的信息。

注銷

現(xiàn)在除了注銷鏈接外,一切都應(yīng)該正常了。我們可以通過定義注銷路由并直接向其添加一個路由保護來使其工作。

{
    name: "Logout",
    path: "/logout",
    beforeEnter: async () => {
      const { logout } = useAuthUser();
      await logout();
      return { name: "Home" };
    },
  },

注銷后,如果你愿意,你可以嘗試用不同的電子郵件再次注冊,以確認我們上面的修復(fù)對直接導航到個人資料頁面起作用。同樣,當注銷后,檢查一下登錄頁面。你應(yīng)該也能用現(xiàn)有的用戶成功登錄!

家庭作業(yè)

最后,如果你使用忘記密碼的鏈接,Supabase確實會向你發(fā)送重置密碼的電子郵件,然而你仍然需要實現(xiàn)該表格。我敢說,你可以利用你在文章中所學到的知識來研究這個問題,并利用AuthUser可組合的update 方法。

總結(jié)

Supabase是Firebase的一個新的和即將到來的替代品。它有很多誘人的特點,比如開源,使用PostgreSQL作為數(shù)據(jù)庫,并提供流行的服務(wù),如數(shù)據(jù)存儲、認證和文件存儲。用他們的認證服務(wù)來認證你的Vue.js 3應(yīng)用程序是相當簡單的,因為他們的認證api很簡單。

如果你想看看本文討論的完整代碼,你可以查看Github repo

一旦認證完成,你就可以開始向你的Supabase實例發(fā)出請求,并創(chuàng)建規(guī)則來限制哪些用戶可以訪問哪些數(shù)據(jù)。

因此,去制作真實的Supabase應(yīng)用程序吧。

https://vueschool.io/courses/vuejs-3-fundamentals?ref=blog

以上就是Vue3中使用Supabase Auth方法詳解的詳細內(nèi)容,更多關(guān)于Vue3中使用Supabase Auth的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論