完整的 Jii-Secure 整合指南與 API 文檔。快速開始使用企業級身份認證服務。
Jii-Secure 是一個現代化的企業級身份認證服務,提供完整的用戶管理、JWT 認證、Email 驗證等功能。
這是一個完整的認證中間件範例,展示如何在您的應用中整合 Jii-Secure:
package middleware
import (
"fmt"
"net/http"
"net/url"
)
// AuthMiddleware 檢查用戶是否已登入(是否有 token)。
// 如果沒有,則重定向到登入頁面並帶上 "next" 參數。
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 檢查 cookies 中的 auth token
cookie, err := r.Cookie("auth_token")
if err != nil || cookie.Value == "" {
// 未登入
// 構建帶有 "next" 參數的回調 URL(用戶想要訪問的頁面)
nextPath := r.URL.Path
if r.URL.RawQuery != "" {
nextPath += "?" + r.URL.RawQuery
}
// 回調 URL 本身需要編碼 'next' 參數
callbackUrl := fmt.Sprintf("%s/callback?next=%s",
ClientURL, url.QueryEscape(nextPath))
// 重定向到 Jii-Secure 登入頁面,傳遞我們的智能回調 URL
loginUrl := fmt.Sprintf("%s/login.html?redirectUrl=%s",
MemAuthURL, url.QueryEscape(callbackUrl))
http.Redirect(w, r, loginUrl, http.StatusFound)
return
}
// 用戶已登入,驗證 token 有效性(為簡潔起見省略,通常驗證簽名)
// 傳遞給下一個處理器
next.ServeHTTP(w, r)
})
}
處理從 Jii-Secure 返回的認證回調:
// CallbackHandler 處理從 Jii-Secure 返回的認證回調
func CallbackHandler(w http.ResponseWriter, r *http.Request) {
// 獲取 token
token := r.URL.Query().Get("token")
if token == "" {
http.Error(w, "Missing token", http.StatusBadRequest)
return
}
// 驗證 token
valid, err := verifyToken(token)
if err != nil || !valid {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
// 設置 cookie
http.SetCookie(w, &http.Cookie{
Name: "auth_token",
Value: token,
Path: "/",
HttpOnly: true,
Secure: true,
MaxAge: 86400, // 24小時
})
// 獲取原始目標路徑
nextPath := r.URL.Query().Get("next")
if nextPath == "" {
nextPath = "/"
}
// 重定向到原始頁面
http.Redirect(w, r, nextPath, http.StatusFound)
}
func verifyToken(token string) (bool, error) {
// 向 Jii-Secure API 驗證 token
resp, err := http.Post(
MemAuthURL+"/auth/verifytoken",
"application/json",
strings.NewReader(fmt.Sprintf(`{"token":"%s"}`, token)),
)
if err != nil {
return false, err
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
return result["success"].(bool), nil
}
在前端使用 Jii-Secure API 的範例:
// 登入函數
async function login(email, password) {
try {
const response = await fetch('/auth/apilogin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password })
});
const data = await response.json();
if (data.success) {
// 儲存 token
localStorage.setItem('auth_token', data.data.token);
// 重定向到儀表板
window.location.href = '/dashboard';
} else {
alert('登入失敗: ' + data.message);
}
} catch (error) {
console.error('登入錯誤:', error);
}
}
// 獲取用戶資訊
async function getUserInfo() {
const token = localStorage.getItem('auth_token');
try {
const response = await fetch('/auth/user', {
headers: {
'Authorization': 'Bearer ' + token
}
});
const data = await response.json();
if (data.success) {
return data.data;
}
} catch (error) {
console.error('獲取用戶資訊錯誤:', error);
}
return null;
}
// 登出函數
function logout() {
localStorage.removeItem('auth_token');
window.location.href = '/';
}
import { useState, useEffect } from 'react';
function useAuth() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
checkAuth();
}, []);
const checkAuth = async () => {
const token = localStorage.getItem('auth_token');
if (!token) {
setLoading(false);
return;
}
try {
const response = await fetch('/auth/user', {
headers: {
'Authorization': 'Bearer ' + token
}
});
const data = await response.json();
if (data.success) {
setUser(data.data);
} else {
localStorage.removeItem('auth_token');
}
} catch (error) {
console.error('驗證錯誤:', error);
localStorage.removeItem('auth_token');
}
setLoading(false);
};
const login = async (email, password) => {
const response = await fetch('/auth/apilogin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password })
});
const data = await response.json();
if (data.success) {
localStorage.setItem('auth_token', data.data.token);
await checkAuth();
return true;
}
return false;
};
const logout = () => {
localStorage.removeItem('auth_token');
setUser(null);
};
return { user, loading, login, logout };
}
公開 註冊新用戶
{
"name": "張三",
"email": "[email protected]",
"password": "secure_password_123"
}
{
"success": true,
"message": "註冊成功",
"data": {
"user_id": 123,
"email": "[email protected]",
"verification_sent": true
}
}
公開 用戶登入
{
"email": "[email protected]",
"password": "secure_password_123"
}
{
"success": true,
"message": "登入成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires_at": "2025-12-31T23:59:59Z",
"user": {
"id": 123,
"name": "張三",
"email": "[email protected]",
"is_verified": true
}
}
}
需要認證 獲取當前用戶資訊
Authorization: Bearer YOUR_JWT_TOKEN
{
"success": true,
"data": {
"id": 123,
"name": "張三",
"email": "[email protected]",
"is_verified": true,
"created_at": "2025-01-15T10:30:00Z"
}
}
公開 驗證 JWT token
{
"token": "eyJhbGciOiJIUzI1NiIs..."
}
所有 API 端點都會返回標準的錯誤格式:
{
"success": false,
"message": "錯誤描述",
"error_code": "ERROR_CODE"
}
| 錯誤碼 | 說明 | HTTP 狀態 |
|---|---|---|
INVALID_CREDENTIALS |
帳號或密碼錯誤 | 401 |
TOKEN_EXPIRED |
Token 已過期 | 401 |
INVALID_TOKEN |
無效的 Token | 401 |
EMAIL_EXISTS |
Email 已被註冊 | 400 |
VALIDATION_ERROR |
輸入驗證失敗 | 400 |
在 .env 檔案中配置以下變數:
# 服務配置
PORT=8080
HOST=localhost
# JWT 配置
JWT_SECRET=your-secret-key-here
JWT_EXPIRY=24h
# 資料庫配置
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=password
DB_NAME=jii_secure
# Email 配置
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=your-app-password
# 應用 URL
CLIENT_URL=http://localhost:3000
API_URL=http://localhost:8080
運行資料庫遷移:
# 初始化資料庫
go run migrate.go up
# 回滾遷移
go run migrate.go down
如果您遇到問題或有疑問:
我們歡迎各種形式的貢獻!
# Fork 專案並克隆
git clone https://github.com/YOUR_USERNAME/jii-secure.git
# 創建新分支
git checkout -b feature/amazing-feature
# 提交更改
git commit -m 'Add some amazing feature'
# 推送到分支
git push origin feature/amazing-feature
# 開啟 Pull Request
本專案採用 MIT 授權協議。詳情請參閱 LICENSE 文件。
MIT License
Copyright (c) 2025 Jii-Secure
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.