当前位置: 首页 > news >正文

java后端对接飞书登陆

java后端对接飞书登陆
在这里插入图片描述

项目要求对接第三方登陆,飞书登陆,次笔记仅针对java后端,在看本笔记前,默认已在飞书开发方已建立了应用,并获取到了appid和appsecret。后端要做的其实很简单,基本都是前端做的,后端要做的就是接收前端请求飞书获取到一个code后传到后端,后端拿到code后请求登陆人在飞书的token信息,同时根据token请求飞书接口获取登陆人信息返回给前端就好了,官网开发指导有很详细的教程,可以看下官方文档。
飞书官方文档
废话不多书,直接上代码:
首先controller:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** @author xx*/
@RestController
@Api(tags = "飞书登陆认证")
public class FeiShuController {@Resourceprivate FeiShuService feiShuService;@GetMapping("/getUserByCode/{code}")@ApiOperation(value = "根据code获取飞书用户信息")public Response<FeishuUserResp> login(@PathVariable String code) {//获取飞书用户tokenFeiShuTokenResp feiShuTokenVo = feiShuService.getTokenByCode(code);//根据token获取用户信息FeishuUserResp userInfo = feiShuService.getUserInfoByToken(feiShuTokenVo);// 刷新tokenreturn Response.ok(userInfo);}@GetMapping("/refreshToken/{refreshToken}")@ApiModelProperty(value = "刷新token")public Response<FeishuUserResp> refreshToken(@PathVariable String refreshToken){return Response.ok(feiShuService.refreshToken(refreshToken));}@PostMapping("/login-out/{userId}")@ApiOperation(value = "飞书退出登陆")public Response loginOut(HttpServletRequest request, @PathVariable String userId){return feiShuService.loginOut(request,userId);}
}

service层:

import cn.hutool.http.Header;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;@Slf4j
@Service
public class FeiShuServiceImpl implements FeiShuService {// 应用appid@Value("${feishu.app.id}")private String appid;// 应用appsecret@Value("${feishu.app.secret}")private String appsecret;// 飞书获取token地址@Value("${feishu.userAccessTokenUrl}")private String userAccessTokenUrl;// 回调地址(需前端提供)@Value("${feishu.redirectUrl}")private String redirectUrl;// 获取用户详情@Value("${feishu.userInfoUrl}")private String userInfoUrl;// 登出飞书地址@Value("${feishu.logOutUrl}")private String loginOutUrl;//刷新飞书token地址@Value("${feishu.refreshTokenUrl}")private String refreshTokenUrl;@Resourceprivate RedisService redisService;/*** 根据code获取token** @param code code* @return token*/@Overridepublic FeiShuTokenResp getTokenByCode(String code) {Map<String, Object> params = new HashMap<>(4);params.put("grant_type", "authorization_code");params.put("client_id", appid);params.put("client_secret", appsecret);params.put("code", code);params.put("redirect_uri", redirectUrl);String result = HttpUtil.createPost(userAccessTokenUrl).header(Header.CONTENT_TYPE, "application/json").charset("utf-8").body(JSON.toJSONString(params)).execute().body();if (StringUtils.isEmpty(result)) {throw new RuntimeException("获取飞书token失败!");}JSONObject parseObj = JSONUtil.parseObj(result);if ((int) parseObj.get("code") != 0) {throw new RuntimeException("请求飞书token失败:" + parseObj.get("error_description"));}//tokenString userAccessToken = (String) parseObj.get("access_token");//token过期时间long expiresIn = (int) parseObj.get("expires_in");// refresh_tokenString refreshToken = (String) parseObj.get("refresh_token");// 刷新token的过期时间long refreshTokenExpiresIn = (int) parseObj.get("refresh_token_expires_in");// token_typeString tokenType = (String) parseObj.get("token_type");return FeiShuTokenResp.builder().tokenType(tokenType).accessToken(userAccessToken).expiresIn(expiresIn).refreshToken(refreshToken).refreshTokenExpiresIn(refreshTokenExpiresIn).build();}/*** 获取用户详情** @return 用户信息*/@Overridepublic FeishuUserResp getUserInfoByToken(FeiShuTokenResp feiShuTokenVo) {String token = feiShuTokenVo.getTokenType() + " " + feiShuTokenVo.getAccessToken();String result = HttpUtil.createGet(userInfoUrl).header("Authorization", token).header(Header.CONTENT_TYPE, "application/json").charset("utf-8").execute().body();if (StringUtils.isEmpty(result)) {throw new RuntimeException("请求飞书用户详情接口失败!");}JSONObject parseObj = JSONUtil.parseObj(result);if ((int) parseObj.get("code") != 0) {throw new RuntimeException("获取飞书用户信息失败:" + parseObj.get("msg"));}Object data = parseObj.get("data");FeishuUserResp userResp = JSONUtil.toBean(JSONUtil.toJsonStr(data), FeishuUserResp.class);userResp.setAccessToken(feiShuTokenVo.getAccessToken());userResp.setRefreshToken(feiShuTokenVo.getRefreshToken());// 缓存tokenString tokenKey = GlobalConstant.TOKEN + ":" + feiShuTokenVo.getAccessToken();redisService.setCacheObject(tokenKey, feiShuTokenVo.getAccessToken(), feiShuTokenVo.getExpiresIn(), TimeUnit.SECONDS);//缓存用户信息redisService.setCacheObject(feiShuTokenVo.getAccessToken(), userResp, feiShuTokenVo.getExpiresIn(), TimeUnit.SECONDS);//缓存刷新tokenif (Objects.nonNull(feiShuTokenVo.getRefreshToken())) {String refreshTokenKey = GlobalConstant.REFRESH_TOKEN + ":" + feiShuTokenVo.getRefreshToken();redisService.setCacheObject(refreshTokenKey, feiShuTokenVo.getRefreshToken(), feiShuTokenVo.getRefreshTokenExpiresIn(), TimeUnit.SECONDS);//缓存redisService.setCacheObject(feiShuTokenVo.getRefreshToken(), userResp, feiShuTokenVo.getRefreshTokenExpiresIn(), TimeUnit.SECONDS);}return userResp;}/*** 飞书退出登陆** @param userId user_id* @return 返回*/@Overridepublic Response loginOut(HttpServletRequest request, String userId) {String token = request.getHeader(GlobalConstant.TOKEN);Map<String, Object> params = new HashMap<>(2);params.put("logout_type", 1);params.put("user_id", userId);String result = HttpUtil.createPost(loginOutUrl).header("Authorization", "").header(Header.CONTENT_TYPE, "application/json").charset("utf-8").body(JSONUtil.toJsonStr(params)).execute().body();if (result == null) {throw new RuntimeException("飞书退出登陆失败!");}JSONObject parseObj = JSONUtil.parseObj(result);//删除缓存tokenFeishuUserResp object = redisService.getCacheObject(token);redisService.deleteObject(object.getAccessToken());redisService.deleteObject(object.getRefreshToken());redisService.deleteObject(GlobalConstant.TOKEN + ":" + token);redisService.deleteObject(GlobalConstant.REFRESH_TOKEN + ":" + object.getRefreshToken());if ((int) parseObj.get("code") == 0) {return Response.ok();}return Response.failed(parseObj.get("msg").toString());}/*** 刷新token** @param refreshToken 刷新token* @return 返回*/@Overridepublic FeishuUserResp refreshToken(String refreshToken) {Map<String, String> params = new HashMap<>(4);params.put("grant_type", "refresh_token");params.put("client_id", appid);params.put("client_secret", appsecret);params.put("refresh_token", refreshToken);String result = HttpUtil.createPost(refreshTokenUrl).header(Header.CONTENT_TYPE, "application/json").charset("utf-8").body(JSONUtil.toJsonStr(params)).execute().body();if (Objects.isNull(result)) {throw new RuntimeException("刷新token失败!");}JSONObject parseObj = JSONUtil.parseObj(result);if (20037 == (int) parseObj.get("code")) {throw new RuntimeException("refresh_token已过期");}if (0 != (int) parseObj.get("code")) {throw new RuntimeException("请求飞书刷新token接口失败:" + parseObj.get("error_description"));};//tokenString token = (String) parseObj.get("access_token");//token过期时间long expiresIn = (long) parseObj.get("expires_in");//刷新tokenString refreshToken1 = (String) parseObj.get("refresh_token");//刷新token 过期时间long refreshTokenExpiresIn = (long) parseObj.get("refresh_token_expires_in");FeishuUserResp resp = redisService.getCacheObject(refreshToken);resp.setAccessToken(token);resp.setRefreshToken(refreshToken1);//缓存tokenredisService.setCacheObject(GlobalConstant.TOKEN + ":" + token, token, expiresIn, TimeUnit.MINUTES);redisService.setCacheObject(token, resp, expiresIn, TimeUnit.MINUTES);Object object = redisService.getCacheObject(GlobalConstant.REFRESH_TOKEN + ":" + refreshToken1);if (Objects.isNull(object)) {redisService.setCacheObject(GlobalConstant.REFRESH_TOKEN + ":" + refreshToken1, refreshToken1, refreshTokenExpiresIn, TimeUnit.MINUTES);redisService.setCacheObject(refreshToken1, resp, refreshTokenExpiresIn, TimeUnit.MINUTES);}return resp;}
}

yml文件飞书相关配置

#  飞书相关配置
feishu:app:id: "xxxxxx"secret: "xxxxxx"# 获取token地址userAccessTokenUrl: "https://open.feishu.cn/open-apis/authen/v2/oauth/token"# 回调地址(可更改)redirectUrl: "http://xxxxxx/upgrade/login"# 获取用户信息地址userInfoUrl: "https://open.feishu.cn/open-apis/authen/v1/user_info"# 登出logOutUrl: "https://open.feishu.cn/open-apis/passport/v1/sessions/logout"# 刷新token地址refreshTokenUrl: "https://open.feishu.cn/open-apis/authen/v2/oauth/token"

学习笔记仅供学习使用,更详细步骤请移步官方文档。

相关文章:

java后端对接飞书登陆

java后端对接飞书登陆 项目要求对接第三方登陆&#xff0c;飞书登陆&#xff0c;次笔记仅针对java后端&#xff0c;在看本笔记前&#xff0c;默认已在飞书开发方已建立了应用&#xff0c;并获取到了appid和appsecret。后端要做的其实很简单&#xff0c;基本都是前端做的&…...

记录一次Android Studio的下载、安装、配置

目录 一、下载和安装 Android Studio 1、搜索下载Android studio ​2、下载成功后点击安装包进行安装&#xff1a; 3、这里不用打勾&#xff0c;直接点击安装 &#xff1a; 4、完成安装&#xff1a; 5、这里点击Cancel就可以了 6、接下来 7、点击自定义安装&#xff1a…...

直流无刷电机控制(FOC):电流模式

目录 概述 1 系统框架结构 1.1 硬件模块介绍 1.2 硬件实物图 1.3 引脚接口定义 2 代码实现 2.1 软件架构 2.2 电流检测函数 3 电流环功能实现 3.1 代码实现 3.2 测试代码实现 4 测试 概述 本文主要介绍基于DengFOC的库函数&#xff0c;实现直流无刷电机控制&#x…...

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…...

垃圾收集算法

分代收集理论 分代收集理论&#xff0c;建立在两个分代假说之上。 弱分代假说&#xff1a;绝大多数对象都是朝圣夕灭的。 强分代假说&#xff1a;熬过越多次垃圾收集的过程的对象就越难以消亡。 这两个分代假说奠定了垃圾收集器的一致设计原则&#xff1a;收集器应该将Java…...

SQL-leetcode-262. 行程和用户

262. 行程和用户 表&#xff1a;Trips --------------------- | Column Name | Type | --------------------- | id | int | | client_id | int | | driver_id | int | | city_id | int | | status | enum | | request_at | varchar | --------------------- id 是这张表的主键…...

太原理工大学软件设计与体系结构 --javaEE

这个是简答题的内容 选择题的一些老师会给你们题库&#xff0c;一些注意的点我会做出文档在这个网址 项目目录预览 - TYUT复习资料:复习资料 - GitCode 希望大家可以给我一些打赏 什么是Spring的IOC和DI IOC 是一种设计思想&#xff0c;它将对象的创建和对象之间的依赖关系…...

Leetcode 139. 单词拆分 动态规划

原题链接&#xff1a;Leetcode 139. 单词拆分 递归&#xff0c;超时 class Solution { public:bool isfind(string s,map<string,int>& mp){for(auto x:mp){string wordx.first;if(sword) return true;int nword.size();if(n>s.size()) continue;string s1s.subs…...

python异常机制

异常是什么&#xff1f; 软件程序在运行过程中&#xff0c;非常可能遇到刚刚提到的这些问题&#xff0c;我们称之为异常&#xff0c;英文是Exception&#xff0c;意思是例外。遇到这些例外情况&#xff0c;或者交异常&#xff0c;我们怎么让写的程序做出合理的处理&#xff0c…...

运行爬虫时可能遇到哪些常见问题?

在运行Python爬虫时&#xff0c;可能会遇到以下一些常见问题及相应的解决方法&#xff1a; 1. 请求频繁被封 IP 问题描述&#xff1a;爬虫请求频繁时&#xff0c;网站可能会识别到异常行为并封禁 IP&#xff0c;从而导致后续请求失败。解决方法&#xff1a; 使用代理&#xf…...

BGP与CN2的区别 详解两者在网络传输中的应用与优势

在现代互联网环境中&#xff0c;选择合适的网络传输协议和解决方案对于企业的业务运行至关重要。BGP&#xff08;Border Gateway Protocol&#xff09;和CN2&#xff08;China Telecom Next Carrier Network&#xff09;是两种广泛应用的网络技术&#xff0c;但它们的设计理念、…...

Spring 项目 基于 Tomcat容器进行部署

文章目录 一、前置知识二、项目部署1. 将写好的 Spring 项目先打包成 war 包2. 查看项目工件&#xff08;Artifact&#xff09;是否存在3. 配置 Tomcat3.1 添加一个本地 Tomcat 容器3.2 将项目部署到 Tomcat 4. 运行项目 尽管市场上许多新项目都已经转向 Spring Boot&#xff0…...

“负载均衡”出站的功能、原理与场景案例

在企业日常网络中&#xff0c;外网访问速度不稳定是一个常见问题。特别是多条外网线路并行时&#xff0c;不合理的流量分配会导致资源浪费甚至网络拥堵。而出站负载均衡&#xff0c;正是解决这一问题的关键技术。 作为一种先进的网络流量管理技术&#xff0c;其核心是优化企业内…...

02-51单片机数码管与矩阵键盘

一、数码管模块 1.数码管介绍 如图所示为一个数码管的结构图&#xff1a; 说明&#xff1a; 数码管上下各有五个引脚&#xff0c;其中上下中间的两个引脚是联通的&#xff0c;一般为数码管的公共端&#xff0c;分为共阴极或共阳极&#xff1b;其它八个引脚分别对应八个二极管…...

不同方式获取音频时长 - python 实现

DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” -------------------------------------------------------------…...

【python A* pygame 格式化 自定义起点、终点、障碍】

- pip install pygame test.py(chatgpt版本) 空格键&#xff1a;运行 A* 算法。CtrlC 键&#xff1a;清空路径。CtrlS 键&#xff1a;保存当前地图到 map.json 文件。CtrlL 键&#xff1a;从 map.json 文件加载地图。 import pygame import json from queue import PriorityQ…...

12_Redis发布订阅

1.Redis发布订阅介绍 1.1 基本概念 Redis的发布订阅(Pub/Sub)是一种消息通信模式,允许消息的发布者(Publisher)将消息发布到一个或多个频道(Channel),订阅者(Subscriber)通过订阅这些频道来接收消息。 发布者(Publisher):发送消息的一方,使用PUBLISH命令将消息…...

归并排序:数据排序的高效之道

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

【redis初阶】浅谈分布式系统

目录 一、常见概念 1.1 基本概念 2.2 评价指标&#xff08;Metric&#xff09; 二、架构演进 2.1 单机架构 2.2 应用数据分离架构 2.3 应用服务集群架构 2.4 读写分离/主从分离架构 2.5 引入缓存 ⸺ 冷热分离架构 2.6 数据库分库分表 2.7 业务拆分 ⸺ 引入微服务 redis学习&…...

CatLog的使用

一 CatLog的简介 1.1 作用 CAT&#xff08;Central Application Tracking&#xff09; 是基于 Java 开发的实时应用监控平台&#xff0c;为美团点评提供了全面的实时监控告警服务。 1.2 组成部分 1.2.1 Transaction 1.Transaction 适合记录跨越系统边界的程序访问行为&a…...

如何将B站碎片化缓存视频合并为完整MP4?这个Android工具给你答案

如何将B站碎片化缓存视频合并为完整MP4&#xff1f;这个Android工具给你答案 【免费下载链接】BilibiliCacheVideoMerge 项目地址: https://gitcode.com/gh_mirrors/bi/BilibiliCacheVideoMerge 想象一下这样的场景&#xff1a;你在地铁上打开手机&#xff0c;准备观看…...

避坑指南:n8n调用MinerU MCP时常见的3个配置错误及解决方法

避坑指南&#xff1a;n8n调用MinerU MCP时常见的3个配置错误及解决方法 当你第一次尝试将n8n与MinerU MCP结合使用时&#xff0c;可能会遇到一些令人头疼的配置问题。作为一位经历过无数次调试的老手&#xff0c;我想分享几个最常见的陷阱及其解决方案&#xff0c;希望能帮你节…...

GPU显存稳定性终极检测:使用memtest_vulkan保障显卡健康

GPU显存稳定性终极检测&#xff1a;使用memtest_vulkan保障显卡健康 【免费下载链接】memtest_vulkan Vulkan compute tool for testing video memory stability 项目地址: https://gitcode.com/gh_mirrors/me/memtest_vulkan 显卡显存稳定性直接影响你的游戏体验、设计…...

Koikatu HF Patch终极安装指南:5步解锁游戏全部潜力

Koikatu HF Patch终极安装指南&#xff1a;5步解锁游戏全部潜力 【免费下载链接】KK-HF_Patch Automatically translate, uncensor and update Koikatu! and Koikatsu Party! 项目地址: https://gitcode.com/gh_mirrors/kk/KK-HF_Patch 还在为Koikatu游戏体验不完整而烦…...

别再被AI割韭菜了!这8个AI骗局,一定要避开

常见AI骗局类型虚假AI投资项目 利用AI概念包装传统骗局&#xff0c;承诺高回报率吸引投资。常见话术包括“独家算法”“稳赚不赔”&#xff0c;实际为庞氏骗局或资金盘。山寨AI工具收费 将开源AI模型重新包装后收费&#xff0c;或虚构“高级功能”诱导订阅。例如宣称“ChatGPT专…...

PlayIntegrityFix安全验证解决方案:从问题诊断到实战配置全指南

PlayIntegrityFix安全验证解决方案&#xff1a;从问题诊断到实战配置全指南 【免费下载链接】PlayIntegrityFix Fix Play Integrity (and SafetyNet) verdicts. 项目地址: https://gitcode.com/GitHub_Trending/pl/PlayIntegrityFix 一、验证困境与解决方案概述 Androi…...

如何在Windows系统搭建高效Perl开发环境:Strawberry Perl全攻略

如何在Windows系统搭建高效Perl开发环境&#xff1a;Strawberry Perl全攻略 【免费下载链接】Perl-Dist-Strawberry Tooling to build and package releases for Perl on Windows. 项目地址: https://gitcode.com/gh_mirrors/pe/Perl-Dist-Strawberry 在Windows平台进行…...

终极指南:YimMenu如何让你在GTA V中安全畅玩与个性化定制

终极指南&#xff1a;YimMenu如何让你在GTA V中安全畅玩与个性化定制 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/Y…...

如何用OpCore-Simplify实现黑苹果配置全流程自动化

如何用OpCore-Simplify实现黑苹果配置全流程自动化 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在黑苹果配置领域&#xff0c;每一个硬件参数的调整…...

claw-code 源码详细分析:命令宇宙 vs 工具宇宙——`commands` / `tools` 镜像清单如何驱动路由与 shim 执行?

涉及源码&#xff1a;src/reference_data/commands_snapshot.json、tools_snapshot.json&#xff0c;src/commands.py、src/tools.py、src/execution_registry.py、src/runtime.py、src/main.py&#xff0c;src/models.py&#xff08;PortingModule&#xff09;。1. 「两个宇宙…...