目录

一、飞书的配置:

二、Node层的接口开发

三、前端相关的开发

四、服务器端鉴权以及客户端的鉴权

背景:公司后台运营项目采用飞书扫码登录方式,扫码登录完之后获取飞书的信息,然后前端通过这些对应的信息生产token,之后在请求后端接口时讲token通过header传参,并进行鉴权

项目的技术框架是基于Refine+ant-design框架去开发的

一、飞书的配置:

1、首先打开飞书开放平台,然后创建一个应用,

2、然后进行安全设置,重定向URL是在页面用户扫码之后跳转的地址,不配置的话我们在调飞书接口获取飞书用户的信息时就会400

3、接着我们可以去到【权限管理】对获取信息的权限进行一些配置,例如我想获取用户id和邮箱,默认是不返回这两个信息的,那我就需要自己去配置,有些配置需要审核权限,那我们就需要进行发版(发版在【应用发布】-【版本管理与发布】),发版的审核会流到对应企业的管理员那里,审核通过后就能获取到对应的信息了。

4、配置完这些信息之后,我们再来看飞书扫码对应的文档开发文档 - 飞书开放平台进行开发

二、Node层的接口开发

1、总体流程:前端获取到code之后,将code传给后端,后端调用飞书服务器来获取可用于访问用户信息的 access_token,当后端获取到access_token之后,通过 access_token 来调用飞书服务器来获取用户信息。(注意:在飞书文档里面有强调,不要把access_token传递给客户端,因此后端可以将获取access_token以及获取用户信息的接口合为一个接口给前端调用,入参为code和redirect_uri,出参为用户相关的信息以及将用户相关的信息转成token,然后在后续需要权限校验的接口通过header传递token进行验证)

2、相关代码的开发

//api/auth/login/index.ts
import axios from 'axios';
import { NextApiRequest, NextApiResponse } from 'next';
import { z } from 'zod';
import * as jose from 'jose';const JWT_SECRET = 'xxxxx';
// 用 code 换取 accessToken
const getAccessToken = async (code: string, redirect_uri: string) => {const options = {method: 'post',headers: { 'Content-Type': 'application/x-www-form-urlencoded' },params: {['client_id']: '管理后台获取',['client_secret']: '管理后台获取',['grant_type']: 'authorization_code',code,redirect_uri,},url: `https://passport.feishu.cn/suite/passport/oauth/token`,};return await axios(options).then(({ data }) => data);
};const getUserInfo = async (access_token: string) => {const options = {method: 'get',headers: { Authorization: `Bearer ${access_token}` },url: `https://passport.feishu.cn/suite/passport/oauth/userinfo`,};return await axios(options).then(({ data }) => data);
};export default async function login(req: NextApiRequest, res: NextApiResponse) {const { body, query } = req;const numberParser = z.object({ code: z.string(), redirect_uri: z.string() });numberParser.parse(query);const { code, redirect_uri } = query;if (code && redirect_uri) {const { access_token } = await getAccessToken(String(code),String(redirect_uri));const userInfo = await getUserInfo(access_token);const { open_id, union_id, user_id, mobile } = userInfo;const jwtToken = await new jose.SignJWT({open_id,union_id,user_id,mobile,})//获取到用户信息之后通过一些字段生成特定token.setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setExpirationTime('1s').sign(new TextEncoder().encode(JWT_SECRET));if (userInfo) {return res.json({statusCode: 200,data: {userInfo,token: jwtToken,expiresTime: new Date().getTime() + 60 * 60 * 24 * 7 * 1000,},});}} else {return res.status(401).json({ message: '用户登录失败,请重试!' });}
}

三、前端相关的开发

1、二维码的获取

1)在_document.tsx文件中引入sdk

<script src="https://sf3-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.2.js"></script>

2、登录页相关代码(展示二维码,扫码成功逻辑)

//创建实例 当用户扫码成功后会触发handleMessage方法然后跳转到【goto】,然后又会携带code跳转到当前的登录页面
const goto = useRef('');
const redirectUri = useRef('');
const QRLoginObj = useRef(null);
useEffect(() => {window.addEventListener('message', handleMessage, false);return () => {// 移除 message 通知,防止再次重定向window.removeEventListener('message', handleMessage, false);};
}, []);useLayoutEffect(() => {redirectUri.current = `${window?.location?.origin}/login`;//重定向地址,需在管理后台进行配置goto.current = `https://passport.feishu.cn/suite/passport/oauth/authorize?
client_id=cli_a3d520b6047e5013&redirect_uri=${redirectUri.current}&response_type=code&state=STATE`;QRLoginObj.current = QRLogin({id: 'login_container',goto: goto.current,width: '250',height: '260',});
}, []);const handleMessage = (event: any) => {const loginTmpCode = event.data;const origin = event.origin; if( QRLoginObj?.current?.matchOrigin(origin) ) {// 若存在 code 则为已扫码或者已授权状态,不做重定向--坑点if (window.location.search.indexOf('code') !== -1) return;window.location.href = `${goto.current}&tmp_code=${loginTmpCode}`;}};return (<div id='login_container'></div>
)

3、获取用户信息相关代码

//当url携带code时则调用获取用户信息的接口
import { useApiUrl, useCustom } from '@pankod/refine-core';
import { useRouter } from 'next/router';
const { query } = router;const { data: loginData, refetch } = useCustom({url: `${apiUrl}/auth/login`,method: 'get',config: {query: {code: String(query?.code),redirect_uri: redirectUri.current || '',},},queryOptions: {enabled: false,},
});//通过接口获取用户信息
useEffect(()=>{if (query?.code) {refetch();}
},[query])

四、服务器端鉴权以及客户端的鉴权

1、服务器端的鉴权是通过中间件的方式实现的,相关代码如下:middleware.ts/前面我们使用new jose.SignJWT()生成token,于是校验权限的时候采用jose.jwtVerify()去校验token的有效性

import * as jose from 'jose';
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server'const JWT_SECRET = 'XXXX';//跟生成token时统一,因此可以选择抽出来统一管理const noVerifyPath = ['/auth']export async function middleware(req: NextRequest) {const { pathname } = req.nextUrl;// 编写认证中间件const auth = async (authorization: string) => {// { Authorization: Bearer token}const token = authorization.replace('Bearer ', '');try {// 报错:token 被篡改或者为空,属于 401 错误:未认证错误。await jose.jwtVerify(token, new TextEncoder().encode(JWT_SECRET));} catch (err) {return NextResponse.redirect(new URL('/api/auth/login/unauthorized', req.url));}// 执行后续逻辑return NextResponse.next();}const isNeedVerify = noVerifyPath.some(path => pathname.indexOf(path) === -1);// 校验逻辑if (isNeedVerify) {/* 权限校验 */const authorization = req.headers.get('Authorization');if (authorization) {return await auth(authorization);} else {return NextResponse.redirect(new URL('/api/auth/login/unauthorized', req.url));}} else {return NextResponse.next();}}export const config = {// 需要中间件过滤的目录matcher: ['/api/:path*'],
}

2、客户端的鉴权是通过axios拦截器拦截相关接口返回的信息,如果返回的,则跳转到登录页,相关代码如下:

//主要代码const notAuthApi = []//不需要鉴权的api,例如登录
clientRequest.interceptors.response.use(async (response: any) => {//  状态码过滤const { config } = response;const { headers, url } = config;const code = +response?.data?.codeif (!notAuthApi.includes(String(url))) {if(code!==200){//TODO:业务处理}return Promise.resolve(response);} else {return Promise.resolve(response);}},(error: any) => {const { response } = error;if (response.status === 401) {// 登录失败 || 登录过期,重定向处理window.open('/login', '_self');}return Promise.reject(error);}
);

Node(Next)+React实现飞书扫码登录+鉴权的详细开发过程相关推荐

  1. Vue - 实现微信扫码登录功能(项目植入微信扫码登录功能)超详细完整流程详解及详细代码及注释,附带完整功能源码、常见问题解决方案

    前言 如果您需要 Nuxt.js 版本的教程,请访问 Nuxt.js - 微信扫码登录功能. 网上的大部分教程都太乱且没有任何注释和解释,对于新手而言简直是根本无从下手, 本文将站在新手小白的角度,从 ...

  2. Nuxt - 实现微信扫码登录功能(SSR 服务端渲染项目植入微信扫码登录功能)超详细完整流程详解及详细代码及注释,附带完整功能源码、常见问题解决方案

    前言 如果您需要 Vue.js 版本的教程,请访问 Vue.js - 微信扫码登录功能. 网上的大部分教程都太乱且没有任何注释和解释,对于新手而言简直是根本无从下手, 本文将站在新手小白的角度,从 0 ...

  3. 如何用企业微信、飞书等扫码登录 Office 365

    鉴于企业微信.飞书.钉钉等移动社交应用的广泛使用,国内很多企业直接利用飞书.企业微信等平台建立了员工身份系统(账号源).在办公时,员工习惯扫码登录业务系统.但对于很多业务应用如微软系 Office 3 ...

  4. Node.js实现二维码扫码登录

    实现客户端扫码登录分为下列四步: 1. Web页面生成二维码 生成的二维码中必须要包含一个用于唯一标识用户的数据,这个唯一标识是为了确保将客户端(手机)与web网页绑定,避免其他人登录了你的账号.在这 ...

  5. 用Android和node.js实现扫码登录

    实现思路 step 1: 网页端提供二维码 step 2: 手机端登录,并保存token,手机扫码后向网页端发送token step 3: 网页端通过jstoken解析token,向后端服务器获取用户 ...

  6. AbpVnext 扩展企业微信扫码登录(钉钉登陆、短信登陆、微信登陆等)Vue框架

    目录 1.开始开发准备 1.1 企业微信扫码登陆接入流程 1.2 开启网页授权登陆 1.3 构造独立窗口登陆二维码 1.4 构造内嵌登陆二维码 @@登陆顺序: 1. 发现文档配置 2. 获取token ...

  7. spring boot 自动跳转登录页面_徒手撸一个扫码登录示例工程

    徒手撸一个扫码登录示例工程 不知道是不是微信的原因,现在出现扫码登录的场景越来越多了,作为一个有追求.有理想新四好码农,当然得紧跟时代的潮流,得徒手撸一个以儆效尤 本篇示例工程,主要用到以下技术栈 q ...

  8. 项目整合微信扫码登录功能

    项目整合微信登录功能 一.准备工作 https://open.weixin.qq.com 1.注册 2.邮箱激活 3.完善开发者资料 4.开发者资质认证 准备营业执照,1-2个工作日审批.300元 5 ...

  9. 修改微信扫码登录,二维码样式

    开工后的第一篇博客,记得在去年给自己定的计划是每月一篇博客,看来有点没有持之以恒,抱歉-,进入正题: 过完年来一直在赶项目进度,期间也遇到很多问题,很想把它分享出来,时间问题吧,没有及时写出来,今天遇 ...

最新文章

  1. Windows 8.1 PLSQL_32连接到RHEL6.1 Oracle10gr2_64
  2. mysql5.7 too many_Mysql 错误too many connections解决方案
  3. python流程控制语句-Python_流程控制语句
  4. PMCAFF | 产品经理的招聘要求调研分析
  5. 七.Hystrix Timeout机制
  6. C++11标准库 - array
  7. 安全预警:独立发布的Oracle严重 CVE-2018-3110 公告
  8. 让Windows Server 2008 + IIS 7+ ASP.NET 支持10万并发请求--转载
  9. [Web Chart系列之五] 4. 实战draw2d(Raphael)之取消Chrome中Label Text 全部选中
  10. [BZOJ2753][SCOI2012]滑雪与时间胶囊(特殊的有向树形图)
  11. JavaScript学习第八天笔记(Function)
  12. ORACLE 树形遍历查询根节点 父节点 子节点
  13. 计算机考研如何选?中国人民大学学长两年考研经验+权威预测
  14. 关于电子信息/计算机类专业从业者相关的证书与职称
  15. c语言反步法编程,CCM模式下Boost电路的反步法非线性控制与仿真.pdf
  16. 今日股市板块利好早知道,全球科技巨头聚齐联手保护云数据
  17. 新手学计算机专用鼠标垫,CS迷注意!教你自制高级鼠标垫
  18. IE8 RC版 兼容模式的表格边框问题
  19. 分享个好用的在线翻译器拍照扫一扫方法
  20. 热闹之后,香港是否会成为Web3的“应许之地”?

热门文章

  1. 什么是 JWT -- JSON WEB TOKEN
  2. 用 Vue 改造 Bootstrap,渐进提升项目框架
  3. Android N 应用内更新
  4. 密歇根大学计算机硕士学制,密歇根大学安娜堡分校学专业设置及学制介绍
  5. nn.CrossEntropyLoss总结
  6. python nii 图像读取,转换成CT 值,设置窗宽窗位,保存成png 图像
  7. BUUCTF WEB PYTHONGINX1
  8. OPA进阶-简洁的推导式comprehensions
  9. MariaDB/Mysql数据库进阶知识
  10. vscode的格式化问题