【功能设计】应用集成平台token授权接入

news2024/10/7 10:17:59

文章目录

  • IPass应用集成平台token授权接入
    • 1.接入流程图:
    • 2.功能设计:
    • 3.测试要点:

IPass应用集成平台token授权接入

1.接入流程图:

image-20230928144847285

功能业务流程描述:

a.调用方从redis获取应用集成平台授权token

b.如果没有拿到,从应用集成平台获取token并更新

c.如果拿到了,但是调用提示token失效,需要返回b,继续获取新的token(可重试)后,往下执行d

d.业务接口携带新的token调用接口

2.功能设计:

  1. OkHttpUtils工具类

    package com.tn.mdm.common.utils.http;
    
    import com.tn.mdm.common.utils.StringUtils;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.StatusLine;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.*;
    import java.net.*;
    
    public class OkHttpUtils {
    
        private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
    
        public static final RequestConfig queryRequestConfig = RequestConfig.custom().
                setConnectionRequestTimeout(60000).  // 指从连接池获取连接的timeout
                setConnectTimeout(60000).  // 指客户端和服务器建立连接的timeout,
                setSocketTimeout(60000).  // 指客户端和服务器建立连接后,客户端从服务器读取数据的timeout,超出后会抛出SocketTimeOutException
                build();
    
    
        public static String sendGet(String url, String param, String identityToken) {
            StringBuilder result = new StringBuilder();
            BufferedReader in = null;
            URLConnection connection = null;
            try {
                String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
                URL realUrl = new URL(urlNameString);
                connection = realUrl.openConnection();
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                connection.setRequestProperty("identitytoken", identityToken);
                connection.connect();
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
            } catch (ConnectException e) {
                log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
            } catch (SocketTimeoutException e) {
                log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
            } catch (IOException e) {
                log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
                if (connection instanceof HttpURLConnection) {
                    int responseCode = 0;
                    try {
                        responseCode = ((HttpURLConnection) connection).getResponseCode();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    if (responseCode == 401) {
                        // 身份验证失败
                        InputStream errorStream = ((HttpURLConnection) connection).getErrorStream();
                        if (errorStream != null) {
                            try {
                                in = new BufferedReader(new InputStreamReader(errorStream, "UTF-8"));
                            } catch (UnsupportedEncodingException unsupportedEncodingException) {
                                unsupportedEncodingException.printStackTrace();
                            }
                            StringBuilder errorMsgBuilder = new StringBuilder();
                            String line = null;
                            while (true) {
                                try {
                                    if (!((line = in.readLine()) != null)) break;
                                } catch (IOException ioException) {
                                    ioException.printStackTrace();
                                }
                                errorMsgBuilder.append(line);
                            }
                            String errorMsg = errorMsgBuilder.toString();
                            result.append(errorMsg);
                        }
                    }
                }
    
            } catch (Exception e) {
                System.out.println("异常");
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception ex) {
                    log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
                }
            }
            return result.toString();
        }
    
    
        public static String sendPost(String url, String param, String identityToken)
        {
            PrintWriter out = null;
            BufferedReader in = null;
            StringBuilder result = new StringBuilder();
            try
            {
                log.info("sendPost - {}", url);
                URL realUrl = new URL(url);
                URLConnection conn = realUrl.openConnection();
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                conn.setRequestProperty("Accept-Charset", "utf-8");
                conn.setRequestProperty("contentType", "utf-8");
                conn.setRequestProperty("identitytoken", identityToken);
                conn.setDoOutput(true);
                conn.setDoInput(true);
                out = new PrintWriter(conn.getOutputStream());
                out.print(param);
                out.flush();
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                String line;
                while ((line = in.readLine()) != null)
                {
                    result.append(line);
                }
                log.info("recv - {}", result);
            }
            catch (ConnectException e)
            {
                log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
            }
            catch (SocketTimeoutException e)
            {
                log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
            }
            catch (IOException e)
            {
                log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
                // 身份验证失败返回失败信息处理同上
    
            }
            catch (Exception e)
            {
                log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
            }
            finally
            {
                try
                {
                    if (out != null)
                    {
                        out.close();
                    }
                    if (in != null)
                    {
                        in.close();
                    }
                }
                catch (IOException ex)
                {
                    log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
                }
            }
            return result.toString();
        }
    
    }
    
    
  2. 获取/更新 token的工具类

    package com.tn.mdm.common.utils.token;
    
    
    import com.alibaba.fastjson.JSONObject;
    import com.tn.common.tools.exception.base.BusinessException;
    import com.tn.mdm.common.utils.http.HttpUtils;
    import org.springframework.data.redis.core.RedisTemplate;
    
    
    public class TokenUtils {
        private RedisTemplate<String, String> redisTemplate;
        private String redisTokenKey;
        private String host; // 服务器地址
        private String loginUrl; // 登录地址无需修改
        private String userId; // 在API平台中注册的帐号
        private String password; // 帐号的密码,可用md5进行加密一次
        private String token;
    
    
        public TokenUtils(RedisTemplate<String, String> redisTemplate, String redisTokenKey, String host, String loginUrl, String userId, String password) {
            this.redisTemplate = redisTemplate;
            this.host = host;
            this.loginUrl = loginUrl;
            this.userId = userId;
            this.password = password;
            this.redisTokenKey = redisTokenKey;
        }
    
        // 从缓存获取token
        public String getTokenFromRedis() {
            token = redisTemplate.opsForValue().get(redisTokenKey);
            return token;
        }
    
    
        // 更新缓存token
        public void updateTokenToRedis(String newToken) {
            redisTemplate.opsForValue().set(redisTokenKey, newToken);
        }
    
    
        // 从应用集成平台获取新的token
        public String getNewTokenFromPlatform() {
            int maxRetryTimes = 2;
            int retryCount = 0;
            String result = null;
            while (retryCount <= maxRetryTimes) {
                // 获取token
                result = HttpUtils.sendPost(loginUrl, "userName=" + userId + "&password=" + password);
                JSONObject jsonObject = JSONObject.parseObject(result);
                String state = String.valueOf(jsonObject.get("state"));
                if (state != null && state.equals("false")) {
                    retryCount++;
                    continue;
                } else {
                    token = (String) jsonObject.get("identitytoken");
                    return token;
                }
            }
            // 重试次数超过最大重试次数
            throw new BusinessException("系统登录失败" + result + retryCount);
        }
    }
    
    
  3. 业务接口执行获取redis token,如果业务接口调用返回token失效,需要重新拿取token并重试

        @Override
        public ResultResponse test(String orgId) {
            String param = "orgId=" + orgId;
            String sign = null;
            try {
                sign = "&sign=" + Md5Utils.md5(param, crmsConfig.getMd5passwd());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            TokenUtils tokenUtils = new TokenUtils(redisCache.redisTemplate,
                    "iPass_token",
                    iPassConfig.getHost(),
                    iPassConfig.getLoginUrl(),
                    iPassConfig.getUserId(),
                    iPassConfig.getPassword());
            // 从缓存获取token
            String identityToken = tokenUtils.getTokenFromRedis();
            if (StringUtils.isEmpty(identityToken)) {
                // 缓存中没有
                identityToken = tokenUtils.getNewTokenFromPlatform();
                tokenUtils.updateTokenToRedis(identityToken);
            }
            // 缓存中有
            String result = OkHttpUtils.sendGet(iPassConfig.getTest(), param + sign, identityToken);
            JSONObject jsonObject = JSONObject.parseObject(result);
            // 如果调用token失效
            if (jsonObject.containsKey("msg")) {
                if (jsonObject.get("msg").equals("AppKey认证失败")) {
                    identityToken = tokenUtils.getNewTokenFromPlatform();
                    tokenUtils.updateTokenToRedis(identityToken);
                    result = OkHttpUtils.sendGet(iPassConfig.getTest(), param + sign, identityToken);
                    jsonObject = JSONObject.parseObject(result);
                }
            }
            return ResultResponse.success(jsonObject.get("data"));
        }
    

3.测试要点:

以下测试点已验证通过:

  1. 模拟缓存中有token
  2. 模拟缓存中无token时,请求获取token
  3. 模拟缓存中无token时,请求获取token 3次后失败
  4. 模拟业务调用时缓存中token失效

返回成功:

{
    "data": {
        "total": 1,
        "rows": [
            {
                "positionName": "苏南大区-9",
                "positionId": "3_H3M0H",
                "positionUserName": "孙承剑"
            }
        ]
    },
    "flag": true,
    "code": 200,
    "error": null,
    "message": null
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[linux] SFTP文件传输基本命令 --- xshell 直接上传文件

2.sftp - 上传文件&#xff1a;如果上传/下载的是文件夹, 在put/get命令后加上-r参数即可。 上传文件&#xff1a; 把本地服务器的/www/wwwroot目录下面的study.log文件上传到远程服务器的/www/server目录下。 sftp> lcd /www/wwwroot sftp> put study.log /www/server…

数据结构与算法-顺序表

数据结构与算法 &#x1f388;1.线性表&#x1f50e;1.1基本操作&#x1f50e;1.2线性表的存储结构 &#x1f388;2.线性表的顺序表示和实现&#x1f50e;2.1线性表的顺序存储表示&#x1f52d;2.1.1静态顺序表&#x1f52d;2.1.2动态顺序表 &#x1f50e;2.2顺序表基本操作的实…

C/C++/VS2022/指针/数组 调试出现debug

这个情况就很难受&#xff0c;编译没错&#xff0c;但是运行出现问题了&#xff0c;如果点击中止&#xff08;重试、忽略&#xff09;下一次运行还是会出现&#xff0c;看了显示的大致意思是在数组arry上出现了什么错误&#xff0c;经过检查发现&#xff0c;原来是数组在数入时…

李沐深度学习记录2:10多层感知机

一.简要知识记录 x.numel()&#xff1a;看向量或矩阵里元素个数 A.sum()&#xff1a;向量或矩阵求和&#xff0c;axis参数可对某维度求和&#xff0c;keepdims参数设置是否保持维度不变 A.cumsum&#xff1a;axis参数设置沿某一维度计算矩阵累计和x*y:向量的按元素乘法 torch.…

【Golang】并发

并发 有人把Go语言比作 21 世纪的C语言 第一是因为Go语言设计简单 第二则是因为 21 世纪最重要的就是并发程序设计&#xff0c;而 Go 从语言层面就支持并发。同时实现了自动垃圾回收机制 先来了解一些概念&#xff1a; 进程/线程 进程是程序在操作系统中的一次执行过程&#…

MySQL锁的详细讲解(全局锁、表级锁、行级锁)

# 概述 # 全局锁 # 表级锁 表锁 元数据锁 假如有客户端1、客户端2&#xff0c; 客户端1&#xff0c;执行begin命令开启了事务 客户端1没有执行读写语句&#xff0c;这时&#xff0c;客户端执行查看元数据锁的命令&#xff0c;查看到没有加到元数据锁当客户端1执行select读操作…

Ubuntu使用cmake和vscode开发自己的项目

创建文件夹 mkdir my_proj 继续创建include 和 src文件夹&#xff0c;形成如下的目录结构 用vscode打开项目 创建add.h #ifndef ADD_H #define ADD_Hint add(int numA, int numB);#endif add.cpp #include "add.h"int add(int numA, int numB) {return numA nu…

RDP协议流程详解(一)Connection Initiation阶段

Connetction Initiation是RDP连接的第一个阶段&#xff0c;具体包含两个消息RDP Negotiation Request和RDP Negotiation Response&#xff0c;下面结合协议数据包详细分析。 &#xff08;1&#xff09;RDP Negotiation Request 从数据包可以清晰看到此时的协议栈依次是TCP-TPKT…

波奇学C++:map和set

Set的底层是红黑树&#xff0c;红黑树是一种搜索二叉树。 Set的优势在于搜索速度上&#xff0c;搜索key值的时间赋值度是logn。 Set可以实现去重排序的操作&#xff0c;已有的值不再重复插入&#xff0c;插入的数据自动排序 和其他数据结构一样set支出insert,erase,find等操…

ctfshow web入门 php特性 web126-web130

1.web126 和前面一样的 payload&#xff1a; get: a1fl0gflag_give_me post: CTF_SHOW&CTF[SHOW.COM&funparse_str($a[1]) 或 get: ?$fl0gflag_give_me post:CTF_SHOW&CTF[SHOW.COM&funassert($a[0]) assert($a[0]) 是把fl0g赋值为flag_give_me $a[0]是当前…

​【Java】面向对象程序设计 课程笔记 面向对象基础

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;Java &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对你有…

数仓使用SQL脚本在数据库中添加初始数据示例

文章目录 需要在虚拟机上开启数据库 点击确定后&#xff0c;可以点开这个连接&#xff0c;查看数据库信息 运行 init_mysql.sql 创建mall 数据库 -- 设置sql_mode set sql_mode NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES;-- 创建数据库mall create database mall;-- 切换数…

FL水果21编曲宿主软件最新版本更新下载使用教程

rt&#xff0c;楼主受术曲和jpop等影响&#xff0c;重新回到了FL编曲圈中来。目前&#xff0c;正在整理一份关于FL界面、快捷键操作、插件音源、风格制作等汇总笔记&#xff0c;笔记内容来源于来自于网上和个人的编曲经历的理解而成&#xff0c;欢迎大家为笔记的制作与完善提供…

【代码阅读笔记】yolov5 rknn模型部署

一、main函数思路 二、值得学习的地方 1、关注yolov5检测流程 2、其中几个重要的结构体 typedef struct {int left;int right;int top;int bottom; } YOLOV5_BOX_RECT; // box坐标信息typedef struct {char name[YOLOV5_NAME_MAX_SIZE];int class_index;YOLOV5_BOX_RECT box…

【重拾计划】深搜广搜 | luogu P1135 奇怪的电梯

luogu P1135 奇怪的电梯 题目描述方法一 : 深搜dfs方法二&#xff1a;广搜bfs其他解法 题目描述 luogu P1135 奇怪的电梯 方法一 : 深搜dfs 从点A出发&#xff0c;找到符合条件的点一直往下搜即可 代码实现如下&#xff1a; #include<iostream> #include<cstdio…

PS 图层剪贴蒙版使用方法

好 我们先打开PS软件 后面我们需要接触图框工具 在学习图框工具之前 先要掌握剪贴蒙版 这里 我们先点击左上角文件 然后选择新建 我们先新建一个画布出来 然后 我们点击 箭头指向处 新建一个空白图层 点击之后 会就多出一个空白图层 我们在这里 找到 矩形选框工具 然后 …

windows环境下使用mmdetection+mmdeploy训练自定义数据集并转成onnx格式部署

目录 实验环境安装conda创建虚拟环境安装pytorch使用 MIM 安装 MMEngine 和 MMCV安装 MMDetection准备自定义数据集修改配置信息开始训练模型转换与推理 实验环境 windows10python&#xff1a;3.8pytorch :1.8.1cuda&#xff1a;11.1mmdet&#xff1a;3.1.0mmcv&#xff1a;2.…

想要精通算法和SQL的成长之路 - 验证二叉树

想要精通算法和SQL的成长之路 - 验证二叉树 前言一. 验证二叉树1.1 并查集1.2 入度以及边数检查 前言 想要精通算法和SQL的成长之路 - 系列导航 并查集的运用 一. 验证二叉树 原题链接 思路如下&#xff1a; 对于一颗二叉树&#xff0c;我们需要做哪些校验&#xff1f; 首先…

C++:stl:stack、queue、priority_queuej介绍及模拟实现和容量适配器deque介绍

本文主要介绍c中stl的栈、队列和优先级队列并对其模拟实现&#xff0c;对deque进行一定介绍并在栈和队列的模拟实现中使用。 目录 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的…

C++篮球俱乐部管理系统

一、 本系统的设计 篮球俱乐部管理系统是一个用于管理篮球俱乐部日常运营和球队管理的软件系统。它提供了一套功能齐全的工具&#xff0c;帮助篮球俱乐部进行会员管理、训练计划安排、比赛管理、场地预订以及财务记录等方面的工作。 该管理系统的主要特点和功能包括&#xff…