Skip to content
Auth

匿名登录

Create and use anonymous users to authenticate with Supabase

启用匿名登录 来构建应用,让用户在不需要输入电子邮件地址、密码、使用 OAuth 提供商或提供任何其他个人身份信息(PII)的情况下,也能获得认证体验。之后,当准备好时,用户可以将一种认证方式关联到他们的账户上。

可以使用匿名登录来构建:

🌐 Anonymous sign-ins can be used to build:

  • 电子商务应用,比如结账前的购物车
  • 全功能演示,无需收集个人信息
  • 临时或一次性账户

匿名登录 #

🌐 Sign in anonymously

调用 signInAnonymously() 方法:

🌐 Call the signInAnonymously() method:

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { data, error } = await supabase.auth.signInAnonymously()

把匿名用户变成永久用户 #

🌐 Convert an anonymous user to a permanent user

将匿名用户转换为永久用户需要将身份关联到该用户。这需要你在你的 Supabase 项目中启用手动关联。

🌐 Converting an anonymous user to a permanent user requires linking an identity to the user. This requires you to enable manual linking in your Supabase project.

🌐 Link an email / phone identity

你可以使用 updateUser() 方法将电子邮件或手机号身份与匿名用户关联。要为匿名用户添加密码,需要先验证用户的电子邮件或手机号。

🌐 You can use the updateUser() method to link an email or phone identity to the anonymous user. To add a password for the anonymous user, the user's email or phone number needs to be verified first.

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { data: updateEmailData, error: updateEmailError } = await supabase.auth.updateUser({
7
email: 'valid.email@supabase.io',
8
})
9
10
// verify the user's email by clicking on the email change link
11
// or entering the 6-digit OTP sent to the email address
12
13
// once the user has been verified, update the password
14
const { data: updatePasswordData, error: updatePasswordError } = await supabase.auth.updateUser({
15
password: 'password',
16
})

🌐 Link an OAuth identity

你可以使用 linkIdentity() 方法将 OAuth 身份链接到匿名用户。

🌐 You can use the linkIdentity() method to link an OAuth identity to the anonymous user.

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { data, error } = await supabase.auth.linkIdentity({ provider: 'google' })

访问控制 #

🌐 Access control

一个匿名用户像永久用户一样扮演 authenticated 角色。你可以使用行级别安全 (RLS) 策略,通过检查 auth.jwt() 返回的 JWT 中的 is_anonymous 声明来区分匿名用户和永久用户:

🌐 An anonymous user assumes the authenticated role like a permanent user. You can use row-level security (RLS) policies to differentiate between an anonymous user and a permanent user by checking for the is_anonymous claim in the JWT returned by auth.jwt():

1
create policy "Only permanent users can post to the news feed"
2
on news_feed as restrictive for insert
3
to authenticated
4
with check ((select (auth.jwt()->>'is_anonymous')::boolean) is false );
5
6
create policy "Anonymous and permanent users can view the news feed"
7
on news_feed for select
8
to authenticated
9
using ( true );

解决身份冲突 #

🌐 Resolving identity conflicts

根据你的应用需求,当匿名用户被转换为永久用户时,可能会出现数据冲突。例如,在电子商务应用的场景下,匿名用户可以在不注册/登录的情况下将商品添加到购物车。当他们决定登录到已有账户时,你需要决定如何解决购物车中的数据冲突:

🌐 Depending on your application requirements, data conflicts can arise when an anonymous user is converted to a permanent user. For example, in the context of an e-commerce application, an anonymous user would be allowed to add items to the shopping cart without signing up / signing in. When they decide to sign-in to an existing account, you will need to decide how you want to resolve data conflicts in the shopping cart:

  1. 用现有账户里的商品覆盖购物车里的商品
  2. 用匿名用户的商品覆盖购物车里的商品
  3. 把购物车里的物品合并起来

将匿名用户关联到现有账户 #

🌐 Linking an anonymous user to an existing account

在某些情况下,你可能需要将匿名用户关联到现有账户,而不是创建一个新的永久账户。这一过程需要手动处理潜在的冲突。下面是一个一般的方法:

🌐 In some cases, you may need to link an anonymous user to an existing account rather than creating a new permanent account. This process requires manual handling of potential conflicts. Here's a general approach:

1
// 1. Get the current session and verify the user is anonymous
2
const { data: anonData, error: anonError } = await supabase.auth.getSession()
3
4
if (!anonData.session?.user?.is_anonymous) {
5
console.log('User is not anonymous. This flow only applies to anonymous users.')
6
return
7
}
8
9
// 2. Attempt to update the user with the existing email
10
const { data: updateData, error: updateError } = await supabase.auth.updateUser({
11
email: 'valid.email@supabase.io',
12
})
13
14
// 3. Handle the error (since the email belongs to an existing user)
15
if (updateError) {
16
console.log('This email belongs to an existing user. Please sign in to that account.')
17
18
// 4. Sign in to the existing account
19
const {
20
data: { user: existingUser },
21
error: signInError,
22
} = await supabase.auth.signInWithPassword({
23
email: 'valid.email@supabase.io',
24
password: 'user_password',
25
})
26
27
if (existingUser) {
28
// 5. Reassign entities tied to the anonymous user
29
// This step will vary based on your specific use case and data model
30
const { data: reassignData, error: reassignError } = await supabase
31
.from('your_table')
32
.update({ user_id: existingUser.id })
33
.eq('user_id', anonData.session.user.id)
34
35
// 6. Implement your chosen conflict resolution strategy
36
// This could involve merging data, overwriting, or other custom logic
37
await resolveDataConflicts(anonData.session.user.id, existingUser.id)
38
}
39
}
40
41
// Helper function to resolve data conflicts (implement based on your strategy)
42
async function resolveDataConflicts(anonymousUserId, existingUserId) {
43
// Implement your conflict resolution logic here
44
// This could involve ignoring the anonymous user's metadata, overwriting the existing user's metadata, or merging the data of both the anonymous and existing user.
45
}

滥用预防和速率限制 #

🌐 Abuse prevention and rate limits

由于匿名用户会被存储在你的数据库中,恶意用户可能滥用这个接口来大幅增加你的数据库大小。强烈建议你启用隐形 CAPTCHA 或 Cloudflare Turnstile来防止匿名登录被滥用。基于 IP 的速率限制为每小时 30 次请求,你可以在你的后台修改该限制。完整的速率限制列表可以在这里查看。

🌐 Since anonymous users are stored in your database, bad actors can abuse the endpoint to increase your database size drastically. It is strongly recommended to enable invisible CAPTCHA or Cloudflare Turnstile to prevent abuse for anonymous sign-ins. An IP-based rate limit is enforced at 30 requests per hour which can be modified in your dashboard. You can refer to the full list of rate limits here.

自动清理 #

🌐 Automatic cleanup

当前无法自动清理匿名用户。相反,你可以通过执行以下 SQL 从项目中删除匿名用户:

🌐 Automatic cleanup of anonymous users is currently not available. Instead, you can delete anonymous users from your project by running the following SQL:

1
-- deletes anonymous users created more than 30 days ago
2
delete from auth.users
3
where is_anonymous is true and created_at < now() - interval '30 days';

资源 #

🌐 Resources