auth-login
约 1350 字大约 5 分钟
2025-08-11
概述
auth-login 边缘函数负责处理用户登录请求,验证用户凭据,并返回用户信息和会话数据。
文件位置
supabase/functions/auth-login/index.tsAPI 端点
- 方法:
POST - 路径:
/auth-login - Content-Type:
application/json
请求参数
请求体
| 参数名 | 类型 | 必需 | 描述 |
|---|---|---|---|
| string | ✅ | 用户邮箱地址 | |
| password | string | ✅ | 用户密码 |
请求示例
{
"email": "user@example.com",
"password": "password123"
}响应格式
成功响应 (200)
{
"success": true,
"message": "登录成功",
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"email_confirmed_at": "2025-08-11T09:00:00Z",
// ... 其他用户字段
},
"session": {
"access_token": "jwt_token",
"refresh_token": "refresh_token",
"expires_in": 3600,
// ... 其他会话字段
},
"userInfo": {
"id": "uuid",
"email": "user@example.com",
"full_name": "张三",
"role": "student",
"avatar_url": null,
"phone": "13800138000",
"is_active": true
}
}
}错误响应
验证错误 (400)
{
"success": false,
"error": "缺少必填字段: email, password"
}邮箱格式错误 (400)
{
"success": false,
"error": "邮箱格式不正确"
}登录失败 (401)
{
"success": false,
"error": "邮箱或密码错误"
}账户停用 (403)
{
"success": false,
"error": "账户已被停用"
}服务器错误 (500)
{
"success": false,
"error": "获取用户信息失败"
}业务流程
1. 请求预处理
- 处理 CORS 预检请求
- 解析请求体中的 JSON 数据
2. 数据验证
- 验证必填字段:
email、password - 验证邮箱格式:使用正则表达式验证
- 所有验证失败返回 400 状态码
3. 用户认证
- 调用
supabase.auth.signInWithPassword()进行身份验证 - 认证失败返回 401 状态码
4. 用户信息获取
- 从
user_info表获取用户详细信息 - 包含角色、头像、电话等扩展信息
- 获取失败返回 500 状态码
5. 账户状态检查
- 检查
is_active字段确认账户状态 - 已停用账户返回 403 状态码
6. 响应返回
- 成功时返回用户信息、会话数据和扩展信息
- 失败时返回相应的错误信息
依赖模块
shared/index.ts
createSupabaseClient()- 创建 Supabase 客户端handleCors()- 处理 CORS 请求createSuccessResponse()- 创建成功响应createValidationError()- 创建验证错误响应createUnauthorizedResponse()- 创建未授权响应createForbiddenResponse()- 创建禁止访问响应createServerErrorResponse()- 创建服务器错误响应safeAsyncHandler()- 安全异步处理器validateRequiredFields()- 验证必填字段isValidEmail()- 邮箱格式验证
数据库查询
user_info 表查询
SELECT id, email, full_name, role, avatar_url, phone, is_active
FROM user_info
WHERE id = $1安全特性
1. 输入验证
- 必填字段检查
- 邮箱格式验证
- 防止空值和无效数据
2. 认证安全
- 使用 Supabase Auth 内置安全机制
- JWT Token 生成和管理
- 密码哈希验证
3. 数据保护
- 敏感信息过滤
- 行级安全策略(RLS)
- 用户权限检查
4. 错误处理
- 统一错误响应格式
- 敏感错误信息隐藏
- 详细日志记录
使用示例
cURL 请求
# 本地开发环境
curl -X POST http://127.0.0.1:54321/functions/v1/auth-login \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-d '{
"email": "user@example.com",
"password": "password123"
}'
# 生产环境
curl -X POST https://your-project.supabase.co/functions/v1/auth-login \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-d '{
"email": "user@example.com",
"password": "password123"
}'JavaScript 客户端
使用 Supabase 客户端(推荐)
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
'your-project-url',
'your-anon-key'
)
// 调用边缘函数
const { data, error } = await supabase.functions.invoke('auth-login', {
body: {
email: 'user@example.com',
password: 'password123'
}
})
if (error) {
console.error('登录失败:', error)
} else {
console.log('登录成功:', data)
// 处理登录成功后的逻辑
const { user, session, userInfo } = data
}使用原生 fetch
const response = await fetch('http://127.0.0.1:54321/functions/v1/auth-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ANON_KEY'
},
body: JSON.stringify({
email: 'user@example.com',
password: 'password123'
})
})
const result = await response.json()
if (result.success) {
console.log('登录成功:', result.data)
// 存储用户信息和会话
localStorage.setItem('user', JSON.stringify(result.data.user))
localStorage.setItem('session', JSON.stringify(result.data.session))
} else {
console.error('登录失败:', result.error)
}Nuxt.js 集成示例
<script setup>
const supabase = useSupabaseClient()
const user = useSupabaseUser()
const loginData = reactive({
email: '',
password: ''
})
const login = async () => {
try {
const { data, error } = await supabase.functions.invoke('auth-login', {
body: loginData
})
if (error) {
throw error
}
// 登录成功,用户状态会自动更新
await navigateTo('/dashboard')
} catch (error) {
console.error('登录失败:', error.message)
}
}
</script>
<template>
<form @submit.prevent="login">
<input v-model="loginData.email" type="email" placeholder="邮箱" required>
<input v-model="loginData.password" type="password" placeholder="密码" required>
<button type="submit">登录</button>
</form>
</template>Python 客户端
使用 Supabase Python 客户端(推荐)
from supabase import create_client, Client
# 初始化客户端
url = "your-project-url"
key = "your-anon-key"
supabase: Client = create_client(url, key)
# 调用边缘函数
try:
response = supabase.functions.invoke(
"auth-login",
invoke_options={
"body": {
"email": "user@example.com",
"password": "password123"
}
}
)
# 检查响应
if response.status_code == 200:
result = response.json()
if result.get("success"):
print("登录成功:")
print(f"用户ID: {result['data']['user']['id']}")
print(f"邮箱: {result['data']['user']['email']}")
print(f"访问令牌: {result['data']['session']['access_token']}")
else:
print(f"登录失败: {result.get('error')}")
else:
print(f"HTTP错误: {response.status_code}")
except Exception as e:
print(f"调用失败: {str(e)}")使用 requests 库
import requests
import json
url = "http://127.0.0.1:54321/functions/v1/auth-login"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ANON_KEY"
}
payload = {
"email": "user@example.com",
"password": "password123"
}
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # 抛出HTTP错误异常
result = response.json()
if result.get("success"):
print("登录成功:")
user_data = result["data"]
print(f"用户信息: {user_data['userInfo']}")
print(f"会话信息: {user_data['session']}")
else:
print(f"登录失败: {result.get('error')}")
except requests.exceptions.RequestException as e:
print(f"请求失败: {str(e)}")
except json.JSONDecodeError as e:
print(f"JSON解析失败: {str(e)}")Flask 应用集成示例
from flask import Flask, request, jsonify, session
from supabase import create_client
app = Flask(__name__)
app.secret_key = 'your-secret-key'
# 初始化 Supabase 客户端
supabase = create_client("your-project-url", "your-anon-key")
@app.route('/login', methods=['POST'])
def login():
try:
data = request.get_json()
email = data.get('email')
password = data.get('password')
# 调用边缘函数
response = supabase.functions.invoke(
"auth-login",
invoke_options={
"body": {"email": email, "password": password}
}
)
if response.status_code == 200:
result = response.json()
if result.get("success"):
# 存储会话信息
session['user'] = result["data"]["user"]
session['token'] = result["data"]["session"]["access_token"]
return jsonify({"success": True, "message": "登录成功"})
else:
return jsonify({"success": False, "error": result.get("error")}), 400
else:
return jsonify({"success": False, "error": "服务器错误"}), 500
except Exception as e:
return jsonify({"success": False, "error": str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)版权所有
版权归属:Evoliant
许可证:MIT