无需访客认证,在网站展示个人Google Calendar的技术咨询
问题:无需访客认证展示个人Google Calendar日程
我想在个人网站展示自己的Google Calendar日程,让他人查看我的可用时间。目前实现的方案需要访客完成Google认证,但我仅需读取自己的日历数据用于展示,完全不需要访问他人的日历。我已在Google Cloud Console配置了API Key、Client ID,但现有方案均要求访客完成账号认证;也试过iframe嵌入方式,但希望获取日历数据后自定义样式。当前的JS和HTML代码会触发访客认证流程(代码如下),寻求无需访客认证即可展示自身日历的可行方法。
现有代码
JS代码
function gapiLoaded() { gapi.load('client', initializeGapiClient); } async function initializeGapiClient() { try { await gapi.client.init({ apiKey: API_KEY, discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"], }); gisLoaded(); } catch (error) { console.error('Error initializing Google Calendar API client:', error); } } function gisLoaded() { const tokenClient = google.accounts.oauth2.initTokenClient({ client_id: CLIENT_ID, scope: 'https://www.googleapis.com/auth/calendar.readonly', callback: handleAuthResponse, }); tokenClient.requestAccessToken(); } function handleAuthResponse(response) { if (response.error) { console.error('Error authenticating:', response); return; } loadCalendarEvents(); } async function loadCalendarEvents() { try { const response = await gapi.client.calendar.events.list({ 'calendarId': CALENDAR_ID, 'timeMin': (new Date()).toISOString(), 'showDeleted': false, 'singleEvents': true, 'maxResults': 10, 'orderBy': 'startTime' }); const events = response.result.items; const calendarDiv = document.getElementById('calendar'); calendarDiv.innerHTML = ''; // Clear loading message events.forEach(event => { const eventDiv = document.createElement('div'); eventDiv.className = 'event'; const titleDiv = document.createElement('div'); titleDiv.className = 'event-title'; titleDiv.textContent = event.summary; eventDiv.appendChild(titleDiv); const timeDiv = document.createElement('div'); timeDiv.className = 'event-time'; const start = event.start.dateTime || event.start.date; timeDiv.textContent = new Date(start).toLocaleString(); eventDiv.appendChild(timeDiv); calendarDiv.appendChild(eventDiv); }); } catch (error) { console.error('Error fetching calendar events:', error); } } window.onload = function() { console.log('window.onload: Page fully loaded'); gapiLoaded(); };
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>St. Patrick's Irish Pub - Menu</title> <link rel="stylesheet" href="calendar.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> <script src="https://accounts.google.com/gsi/client" async defer></script> <script src="https://apis.google.com/js/api.js"></script> </head> <body> <div class="calendar" id="calendar"></div> <script src="calendar2.js"></script> </body> </html>
可行解决方案
方法1:将日历设为公开,用API Key直接访问
这是最简单的前端实现方式,适合可以公开日程的场景:
- 配置日历公开权限
- 打开你的Google Calendar,找到目标日历,点击「设置和共享」
- 在「访问权限设置」中,开启「对所有人可见」,权限选择「查看日程详情」
- 修改前端代码,移除OAuth认证流程
直接用fetch调用Calendar API,无需访客认证:
const API_KEY = '你的API_KEY'; const CALENDAR_ID = '你的日历ID'; async function loadCalendarEvents() { try { // 直接调用Calendar API,用API Key授权 const response = await fetch(`https://www.googleapis.com/calendar/v3/calendars/${CALENDAR_ID}/events?timeMin=${(new Date()).toISOString()}&showDeleted=false&singleEvents=true&maxResults=10&orderBy=startTime&key=${API_KEY}`); if (!response.ok) { throw new Error(`API请求失败: ${response.status}`); } const data = await response.json(); const events = data.items; const calendarDiv = document.getElementById('calendar'); calendarDiv.innerHTML = ''; events.forEach(event => { const eventDiv = document.createElement('div'); eventDiv.className = 'event'; const titleDiv = document.createElement('div'); titleDiv.className = 'event-title'; titleDiv.textContent = event.summary || '无标题'; eventDiv.appendChild(titleDiv); const timeDiv = document.createElement('div'); timeDiv.className = 'event-time'; const start = event.start.dateTime || event.start.date; timeDiv.textContent = new Date(start).toLocaleString(); eventDiv.appendChild(timeDiv); calendarDiv.appendChild(eventDiv); }); } catch (error) { console.error('获取日历事件失败:', error); document.getElementById('calendar').textContent = '加载日程失败,请稍后重试'; } } window.onload = loadCalendarEvents;
修改后的HTML(移除OAuth相关脚本):
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>我的可用日程</title> <link rel="stylesheet" href="calendar.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> </head> <body> <div class="calendar" id="calendar">加载中...</div> <script src="calendar2.js"></script> </body> </html>
注意事项:
- 公开日历意味着任何人都能通过日历ID和API Key访问,请勿在该日历中添加敏感内容
- 在Google Cloud Console的API Key设置里,限制API Key的使用范围为「Google Calendar API」,并添加网站Referrer限制,防止API Key被滥用
方法2:后端代理(适合不想完全公开日历的场景)
如果不想把日历设为公开,可以通过后端服务账号获取数据,前端仅请求自己的后端接口:
- 在Google Cloud Console创建服务账号,下载JSON密钥文件
- 在Google Calendar的共享设置中,添加服务账号邮箱,授予「查看日程详情」权限
- 后端用服务账号调用Calendar API获取数据,提供一个接口给前端
- 前端直接请求自己的后端接口,无需任何认证
这种方法更安全,日历不会公开,API密钥也不会暴露在前端。
内容的提问来源于stack exchange,提问作者Kripthonite
相关产品推荐
相关产品推荐

