一、当登录按钮被点击时发生了什么?

每个React应用都会遇到这样的核心场景:用户点击登录按钮后,系统如何确认他是否是合法用户?又如何判断他能操作哪些功能?我们通过本地超市的会员系统来理解这个问题:

顾客出示会员卡(凭证验证)→ 收银员检查防伪标记(签名验证)→ 根据会员等级开放权限(角色控制)。这种三层验证机制正是现代Web应用的安全基石。


二、JWT:自包含的电子身份证

2.1 工作原理图解

当用户成功登录后,服务器会生成类似这样的数据结构:

// 技术栈:Node.js + Express
const jwt = require('jsonwebtoken');

// 生成示例令牌
const user = { id: 1001, role: 'editor' };
const token = jwt.sign(
  { 
    user,
    // 过期时间(1小时后)
    exp: Math.floor(Date.now() / 1000) + 3600 
  },
  'your-256-bit-secret',
  { algorithm: 'HS256' }
);

这段代码会生成类似eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxMDAx...的令牌,包含三个组成部分:

  • 头部(红色部分):说明使用HS256算法
  • 载荷(紫色部分):携带用户信息和过期时间
  • 签名(蓝色部分):防篡改验证码

2.2 实战注意事项

// 前端拦截器示例(技术栈:React + Axios)
axios.interceptors.request.use(config => {
  const token = localStorage.getItem('jwt');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
    // 重要:避免XSS攻击
    config.withCredentials = true; 
  }
  return config;
});

黄金法则

  1. 始终通过HTTPS传输
  2. 令牌存储优先选择httpOnly的Cookies
  3. 定期刷新令牌(推荐30分钟)

三、OAuth 2.0:第三方授权通行证

3.1 授权码模式流程图解

假设我们要接入GitHub登录:

// 技术栈:React + GitHub OAuth
const redirectToAuth = () => {
  const CLIENT_ID = 'your_github_client_id';
  const SCOPE = 'user:email,repo';
  window.location = `https://github.com/login/oauth/authorize?
    client_id=${CLIENT_ID}&scope=${SCOPE}`;
};

// 回调处理
const handleCallback = async () => {
  const code = new URLSearchParams(window.location.search).get('code');
  const response = await axios.post('/api/oauth/token', { code });
  // 获取访问令牌
  const { access_token } = response.data; 
};

3.2 常见陷阱清单

  • 授权码必须通过后端交换令牌(禁止前端直接处理)
  • PKCE扩展增强移动端安全性
  • 及时撤销不再需要的授权

四、RBAC:指挥中心的权限分配

4.1 权限矩阵设计示例

角色 文章查看 文章编辑 用户管理
访客 × ×
内容编辑 ×
系统管理员

4.2 动态路由控制实现

// 技术栈:React Router v6
const App = () => (
  <Routes>
    <Route path="/" element={<PublicPage />} />
    <Route element={<AuthLayout />}>
      <Route path="dashboard" element={
        <RoleRequired allowedRoles={['admin', 'editor']}>
          <Dashboard />
        </RoleRequired>
      }/>
      <Route path="admin-panel" element={
        <RoleRequired allowedRoles={['admin']}>
          <AdminPanel />
        </RoleRequired>
      }/>
    </Route>
  </Routes>
);

// 权限高阶组件
const RoleRequired = ({ children, allowedRoles }) => {
  const { role } = useAuth();
  return allowedRoles.includes(role) 
    ? children
    : <Navigate to="/unauthorized" />;
};

五、技术选型指南

5.1 安全方案对照表

特性 JWT Session OAuth
状态管理 无状态 有状态 混合
跨域支持 ★★★ ★★ ★★★
第三方集成 困难 困难 容易
令牌吊销 复杂 简单 中等

5.2 典型组合方案

  • 内部系统:JWT + RBAC
  • 公众平台:OAuth + ABAC
  • 混合架构:JWT前端会话 + OAuth第三方接入

六、安全攻防现场

6.1 常见攻击手段

// CSRF攻击示例
<img src="http://bank.com/transfer?to=hacker&amount=1000000">

// 防御措施:SameSite属性设置
app.use(cookieSession({
  keys: ['secret'],
  sameSite: 'strict'
}));

6.2 安全头设置清单

add_header Content-Security-Policy "default-src 'self'";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

七、技术实践路线图

  1. 开发阶段:使用JWT调试模式(方便问题追踪)
  2. 测试阶段:自动化扫描令牌泄漏
  3. 生产环境:开启HSTS强制HTTPS
  4. 监控预警:异常登录检测系统