You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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管理用户登录会话,验证成功后重定向至目标页面:

  1. 先安装依赖:npm install iron-session
  2. 修改回调接口代码:
// 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:10:51