如何集成Github登录

现在越来越多的网站不再自建登录系统,而是采用第三方登录的方式。比如:QQ、微信、微博、Github等。

其中Github登录是偏技术类网站或新一些的网站的首选,因为它的开放API和生态系统非常强大。

那么如何集成Github登录呢?本文介绍前端主导的Github登录流程。

OAuth2.0 基本概念

Github登录使用的是OAuth2.0协议。OAuth2.0是一个授权框架,允许第三方应用获取对用户资源的有限访问权限。

在OAuth2.0中,主要涉及四个角色:

  1. 资源所有者(用户)
  2. 客户端(第三方应用)
  3. 授权服务器(Github的OAuth服务)
  4. 资源服务器(Github的API服务)

创建Github OAuth应用

  1. 登录Github,进入Settings -> Developer settings -> OAuth Apps
  2. 点击"New OAuth App"按钮
  3. 填写应用信息:
    • Application name:应用名称
    • Homepage URL:应用主页URL
    • Application description:应用描述(可选)
    • Authorization callback URL:授权回调URL
  4. 创建完成后,你会获得Client ID和Client Secret

注意:Client Secret 是非常重要的,一定不能放在前端,千万不要泄露给任何人!

前端实现

1. 发起授权请求

const clientId = 'your_client_id';
const redirectUri = 'your_redirect_uri';
const scope = 'read:user user:email'; // 根据需要设置权限范围

function redirectToGithub() {
  const authUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
  window.location.href = authUrl;
}

// 在登录按钮点击时调用
document.getElementById('github-login').addEventListener('click', redirectToGithub);

2. 处理回调

// callback.js
async function handleCallback() {
  const code = new URLSearchParams(window.location.search).get('code');
  if (!code) return;

  try {
    // 向后端发送code获取access token
    const response = await fetch('/api/github/callback', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ code })
    });

    const data = await response.json();
    if (data.access_token) {
      // 保存token并获取用户信息
      localStorage.setItem('github_token', data.access_token);
      await fetchUserInfo(data.access_token);
    }
  } catch (error) {
    console.error('Github登录失败:', error);
  }
}

async function fetchUserInfo(token) {
  try {
    const response = await fetch('https://api.github.com/user', {
      headers: {
        'Authorization': `token ${token}`
      }
    });
    const userInfo = await response.json();
    console.log('用户信息:', userInfo);
    // 处理登录成功后的逻辑
  } catch (error) {
    console.error('获取用户信息失败:', error);
  }
}

// 页面加载时检查是否有授权码
document.addEventListener('DOMContentLoaded', handleCallback);

服务端实现

服务端主要负责处理Github OAuth的核心流程,主要是code换取token必须在服务端进行。用express框架做一个简易示例:

// 使用express框架
const express = require('express');
const axios = require('axios');
const app = express();

// 环境变量中配置
const clientId = process.env.GITHUB_CLIENT_ID;
const clientSecret = process.env.GITHUB_CLIENT_SECRET;

app.post('/api/github/callback', async (req, res) => {
  const { code } = req.body;
  
  try {
    // 使用code换取access token
    const tokenResponse = await axios.post('https://github.com/login/oauth/access_token', {
      client_id: clientId,
      client_secret: clientSecret,
      code: code
    }, {
      headers: {
        Accept: 'application/json'
      }
    });

    const { access_token } = tokenResponse.data;

    // 返回必要信息给前端
    res.json({
      access_token,
    });

  } catch (error) {
    console.error('Github OAuth Error:', error);
    res.status(500).json({
      error: '授权失败'
    });
  }
});

// 启动服务器
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

服务端注意事项

  1. 安全存储

    • Client Secret必须安全存储,推荐使用环境变量
    • 用户token要加密存储在数据库中
  2. Token管理

    • 实现token过期和刷新机制
    • 定期清理无效token
  3. 错误处理

    • 完善的错误日志记录
    • 友好的错误提示
  4. 并发控制

    • 防止重复授权请求
    • 使用Redis等缓存提高性能

最佳实践

  1. 错误处理:实现完善的错误处理机制,为用户提供清晰的错误提示。

  2. Loading状态:在授权过程中显示loading状态,提升用户体验。

  3. Token管理:合理管理access token的存储和刷新机制。

  4. 用户体验:提供清晰的登录按钮和流程提示。

总结

Github OAuth登录的实现并不复杂,关键是要理解OAuth2.0的基本流程,注意安全性问题,并做好错误处理和用户体验优化。通过以上步骤,你就可以为你的应用添加Github登录功能了。

本文主要介绍的是重前端的方式来实现这个,但真实项目中这些事项更应该放在服务端进行,后续有机会再分享重服务端的实现。