Skip to content

认证授权

本系统采用 JWT (JSON Web Token) 进行身份认证,结合 Casbin 实现基于角色的访问控制 (RBAC)。

认证流程

1. 用户登录

用户通过用户名/邮箱和密码进行登录:

bash
POST /api/v1/auth/login

请求体:

json
{
  "username": "admin",
  "password": "password123"
}

响应:

json
{
  "code": 200,
  "message": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "username": "admin",
      "email": "admin@example.com",
      "roles": ["admin"]
    }
  }
}

2. 使用 Token

在后续请求中,需要在 HTTP Header 中携带 token:

bash
Authorization: Bearer <your-jwt-token>

3. Token 刷新

当前 token 有效期为 24 小时,过期后需要重新登录获取新 token。

权限系统

角色类型

  • admin: 系统管理员,拥有所有权限
  • hr: 人力资源管理员,拥有员工管理权限
  • manager: 部门经理,拥有部门内管理权限
  • employee: 普通员工,拥有基础功能权限

权限分类

用户权限

  • user:read: 查看用户信息
  • user:write: 修改用户信息
  • user:delete: 删除用户

员工权限

  • employee:read: 查看员工信息
  • employee:write: 修改员工信息
  • employee:delete: 删除员工
  • employee:create: 创建员工

薪资权限

  • salary:read: 查看薪资信息
  • salary:write: 修改薪资信息
  • salary:approve: 薪资审批

考勤权限

  • attendance:read: 查看考勤记录
  • attendance:write: 修改考勤记录
  • attendance:manage: 考勤管理

权限检查流程

  1. 认证检查: 验证 JWT token 有效性
  2. 角色检查: 验证用户是否具备相应角色
  3. 权限检查: 验证用户是否具备具体操作权限

API 权限要求

公开接口(无需认证)

bash
GET  /api/v1/ping
GET  /api/v1/companies/:id
GET  /api/v1/public/contacts
POST /api/v1/auth/register
POST /api/v1/auth/login
POST /api/v1/companies/join-qr/resolve

需要认证的接口

大部分接口都需要用户登录后才能访问,需要在请求头中携带有效的 JWT token。

需要管理员权限的接口

所有 /api/v1/admin/* 路径下的接口都需要管理员权限:

bash
# 用户管理
GET    /api/v1/admin/users
PUT    /api/v1/admin/users/:id/status

# 部门管理
POST   /api/v1/admin/departments
GET    /api/v1/admin/departments
PUT    /api/v1/admin/departments/:id
DELETE /api/v1/admin/departments/:id

# 员工管理
POST   /api/v1/admin/employees
GET    /api/v1/admin/employees
PUT    /api/v1/admin/employees/:id
DELETE /api/v1/admin/employees/:id

# 薪资管理
POST   /api/v1/admin/salaries
GET    /api/v1/admin/salaries
PUT    /api/v1/admin/salaries/:id
DELETE /api/v1/admin/salaries/:id

中间件

AuthMiddleware

认证中间件,用于验证 JWT token:

go
// 检查 Authorization: Bearer <token>
// 解析 token 并将用户信息存入上下文

AdminMiddleware

管理员权限中间件,用于验证用户是否具有管理员权限:

go
// 检查用户角色是否包含 "admin"
// 如果不是管理员,返回 403 Forbidden

EmployeeContextMiddleware

员工上下文中间件,用于获取当前登录员工的信息:

go
// 根据用户 ID 获取关联的员工信息
// 将员工信息存入上下文供后续处理使用

错误处理

认证错误

json
{
  "code": 401,
  "message": "未认证",
  "error": "Invalid or expired token"
}

权限错误

json
{
  "code": 403,
  "message": "无权限",
  "error": "Insufficient permissions to access this resource"
}

最佳实践

1. Token 安全

  • 不要在客户端长期存储 token
  • 使用 HTTPS 传输 token
  • 定期更换 token
  • 避免在 URL 中传递 token

2. 权限设计

  • 遵循最小权限原则
  • 定期审查用户权限
  • 使用角色而不是直接分配权限
  • 记录权限操作日志

3. 错误处理

  • 不要泄露具体的错误信息
  • 统一的错误响应格式
  • 记录认证失败的尝试
  • 提供清晰的错误提示

示例代码

JavaScript/Node.js

javascript
// 登录获取 token
const login = async (username, password) => {
  const response = await fetch('/api/v1/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ username, password })
  });

  const data = await response.json();
  if (data.code === 200) {
    localStorage.setItem('token', data.data.token);
    return data.data.user;
  }
  throw new Error(data.message);
};

// 带认证的请求
const authenticatedRequest = async (url, options = {}) => {
  const token = localStorage.getItem('token');
  return fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      'Authorization': `Bearer ${token}`
    }
  });
};

Go

go
// 登录
type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

func Login(username, password string) (string, error) {
    req := LoginRequest{Username: username, Password: password}
    var resp struct {
        Code int `json:"code"`
        Data struct {
            Token string `json:"token"`
        } `json:"data"`
    }

    // 发送登录请求
    // 处理响应...
    return resp.Data.Token, nil
}

// 带认证的请求
func AuthenticatedRequest(url string, token string) (*http.Response, error) {
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Set("Authorization", "Bearer "+token)
    return http.DefaultClient.Do(req)
}

故障排除

Token 无效

  • 检查 token 是否过期
  • 验证 token 格式是否正确
  • 确认 JWT_SECRET 配置正确

权限不足

  • 检查用户角色是否正确
  • 验证权限配置是否生效
  • 确认 RBAC 策略是否正确加载

中间件不生效

  • 检查中间件注册顺序
  • 验证路由配置是否正确
  • 确认中间件是否正确实现

基于 MIT 许可发布