NextJS实现跳转自定义URL并处理第三方应用响应的方案咨询
Zel协议第三方应用登录流程实现方案
需求背景
我正在开发一款应用,需要引导用户打开以zel:开头的URL启动第三方应用完成登录,第三方应用登录后会通过回调向我的服务器发送登录完成消息。期望实现的流程:
- 用户点击登录按钮
- 引导用户打开第三方应用并完成登录签名
- 第三方应用通过回调向服务器发送登录结果
- 验证登录状态后,将用户重定向至
/afterlogin路径
现有代码如下:
登录页代码(pages/login.js)
import axios from 'axios'; import { useRouter } from 'next/router'; export default function Login() { const router = useRouter(); const handleClick = () => { axios.get('https://api.runonflux.io/id/loginphrase').then(response => { if (response.data.status === 'success') { var loginPhrase = response.data.data; if (loginPhrase) { router.push(`zel:?action=sign&message=${loginPhrase}&callback=${process.env.DOMAIN}api/validateSignature`); } } }); } return ( <div> <button onClick={handleClick}>Login</button> </div> ) }
说明:登录页点击按钮后请求API获取登录短语,跳转至
zel:协议URL引导第三方应用签名。
回调接口代码(pages/api/validateSignature.js)
export default function handler(req, res) { if (req.method == 'GET') { } var url = "https://api.runonflux.io/id/verifylogin"; var axios = require('axios'); var data = JSON.stringify({ "loginPhrase": req.body.message, "signature": req.body.signature, "zelid": req.body.address }); var config = { method: 'post', url: url, data: data }; axios(config) .then(function (response) { console.log(response.data); }) .catch(function (error) { console.log(error); }); res.status(200).json({ name: 'John Doe' }) }
说明:该接口用于接收第三方应用的回调请求,但目前未完成验证后的状态处理和重定向逻辑。
分步实现方案
一、完善登录页跳转逻辑
解决zel:协议跳转失败场景(如用户未安装应用),改用原生跳转替代Next.js路由:
// pages/login.js 修改后的handleClick函数 const handleClick = () => { axios.get('https://api.runonflux.io/id/loginphrase').then(response => { if (response.data.status === 'success') { const loginPhrase = response.data.data; if (loginPhrase) { const zelUrl = `zel:?action=sign&message=${loginPhrase}&callback=${process.env.DOMAIN}/api/validateSignature`; // 原生跳转自定义协议 window.location.href = zelUrl; // 检测跳转是否成功,未安装应用则提示 setTimeout(() => { alert('请先安装Zel相关应用'); }, 1000); } } }).catch(err => { console.error('获取登录短语失败:', err); alert('登录初始化失败,请重试'); }); }
二、完善回调接口会话管理与重定向
使用iron-session管理用户登录会话,验证成功后重定向至目标页面:
- 先安装依赖:
npm install iron-session - 修改回调接口代码:
// pages/api/validateSignature.js import axios from 'axios'; import { withIronSessionApiRoute } from 'iron-session/next'; // 会话配置,需在环境变量中设置加密密钥 const sessionOptions = { password: process.env.SESSION_PASSWORD, // 至少32位的随机密钥 cookieName: 'zel-login-session', cookieOptions: { secure: process.env.NODE_ENV === 'production', }, }; async function handler(req, res) { // 兼容GET/POST两种回调请求方式 const { message, signature, address } = req.method === 'POST' ? req.body : req.query; // 校验必填参数 if (!message || !signature || !address) { return res.status(400).json({ error: '缺少必要参数' }); } try { // 调用官方验证API const verifyRes = await axios.post('https://api.runonflux.io/id/verifylogin', { loginPhrase: message, signature: signature, zelid: address }); if (verifyRes.data.status === 'success') { // 验证成功,写入会话 req.session.user = { zelId: address, isLoggedIn: true }; await req.session.save(); // 重定向至登录后页面 return res.redirect('/afterlogin'); } else { return res.status(401).json({ error: '签名验证失败' }); } } catch (error) { console.error('验证请求失败:', error); return res.status(500).json({ error: '服务器内部错误' }); } } export default withIronSessionApiRoute(handler, sessionOptions);
三、添加登录状态校验(/afterlogin页面)
确保只有登录用户能访问目标页面:
// pages/afterlogin.js import { withIronSessionSsr } from 'iron-session/next'; import { useRouter } from 'next/router'; import { useEffect } from 'react'; export default function AfterLogin({ user }) { const router = useRouter(); useEffect(() => { if (!user?.isLoggedIn) { router.push('/login'); } }, [user, router]); if (!user?.isLoggedIn) { return <div>正在跳转...</div>; } return ( <div> <h1>登录成功!</h1> <p>你的Zel ID: {user.zelId}</p> </div> ); } export const getServerSideProps = withIronSessionSsr( async ({ req }) => { const user = req.session.user; if (!user?.isLoggedIn) { return { redirect: { destination: '/login', permanent: false, }, }; } return { props: { user: req.session.user }, }; }, { password: process.env.SESSION_PASSWORD, cookieName: 'zel-login-session', cookieOptions: { secure: process.env.NODE_ENV === 'production', }, } );
四、环境变量配置
在.env.local中添加以下配置:
DOMAIN=https://your-app-domain.com/ # 替换为你的应用域名,结尾需加/ SESSION_PASSWORD=your-32-bit-or-longer-secret-password # 生成安全的随机字符串
内容的提问来源于stack exchange,提问作者vmvelev
相关产品推荐
相关产品推荐

