Oauth2.0实战

oauth 2.0

本文为学习极客时间-王新栋老师-《oauth2.0实战》课程的学习笔记,课程链接如下:
https://time.geekbang.org/column/article/254518

一.基础篇

1. oauth 2.0简介

1.oauth2.0是什么?

​ oauth2.0 是一种授权协议,也是一种为委托协议。

​ 你使用小兔软件打印京东订单信息,那么你需要给小兔软件授权,给他访问订单的权限,他才能打印订单。

​ 那么怎么授权呢?你难道直接给他京东账号密码吗? 所以就有了OAUTH2.0协议,由他实现授权流程,资源拥有者确认授权

​ 小兔软件就可获取 accessToken,由accessToken代替用户名密码访问 订单webAPI。

2.解决什么问题?

授权问题(令牌机制实现授权)和安全问题

​ 互联网中所有的受保护资源,几乎都是以 Web API 的形式来提供访问的,比如极客时间 App 要获取用户的头像、昵称,小兔软件要获 取用户的店铺订单,我们说 OAuth 2.0 与安全相关,是用来保护 Web API 的。

3.oauth2.0 的核心是什么?

​ 核心是 颁发授权码,访问令牌使用访问令牌

2. 授权码模式

1.授权码模式中的角色以及流程

​ 角色:资源拥有者(用户),客户端(第三方软件),授权服务器,受保护资源

​ 流程:

​ 核心:颁发授权码, 两次重定向

在这里插入图片描述

2. 可以不要授权码吗?

​ 授权码模式 一定需要 授权码

​ 如果不传授权码,直接返回accessToken,直接到浏览器不安全,如果返回到后端,那么用户和授权服务器之间的链接就会断开,用户点击授权之后会一直停留在 授权页面

3. 授权码模式的两次重定向

第一次: 第三方软件没有 受保护资源 访问权限,将用户 重定向到授权页面

第二次:授权服务器 将授权码信息 重定向 到 第三方软件在 授权服务器注册的地址(一般为登录页面)

3. 授权码模式原理

授权码模式的核心流程有两个:颁发授权码 和 颁发访问令牌

1.客户端 向 授权服务器注册

​ 内容一般有
​ client_id:客户端id,客户端唯一标识

​ client_secret:客户端秘钥

​ scope:授权范围

​ redirect_url: 回调地址

Map<String,String> appMap =  new HashMap<String, String>();//模拟第三方软件注册之后的数据库存储

appMap.put("app_id","APPID_RABBIT");
appMap.put("app_secret","APPSECRET_RABBIT");
appMap.put("redirect_uri","http://localhost:8080/AppServlet-ch03");
appMap.put("scope","nickname address pic");
2. 颁发授权码
	分为 **准备工作****生成授权码**  两个流程
 1. 准备工作

  1. 基本信息校验

     校验客户端是否存在

     校验重定向地址是否相同

     校验权限范围是否和注册的范围一致

   2. 生成授权页面		

 2.生成授权码

 	1. **存储授权码与(用户&客户端的映射)(授权码,客户端+用户唯一标识+有效时间)   且授权码使用后会立即删除**
 	2. **存储授权码与权限的  映射关系 (授权码,权限信息+有效时间),方便给accessToken赋权限**
    
    


Map<String,String[]> codeScopeMap =  new HashMap<String, String[]>();
Map<String,String> codeMap =  new HashMap<String, String>();

String code = generateCode(appId,"USERTEST");//模拟登录用户为USERTEST
codeScopeMap.put(code,rscope);//授权范围与授权码做绑定

private String generateCode(String appId,String user) {
  ...
  String code = strb.toString();
  codeMap.put(code,appId+"|"+user+"|"+System.currentTimeMillis());
  return code;
}
 
3. 颁发 访问令牌
1. 信息验证

   验证客户端是否存在

   验证client_id和client_secret

   校验重定向地址是否相同

   验证用户访问权限

2. 生成访问令牌

    	1. **存储accessToken与(用户&客户端的映射)(accessToken,客户端+用户唯一标识+有效时间)  **
    	2. **存储accessToken与权限的  映射关系 (accessToken,权限信息+有效时间),从授权码那里拿**
    	3. 生层refreshToken,存储两个键值对,分别为  客户端用户关系和权限关系


Map<String,String[]> tokenScopeMap =  new HashMap<String, String[]>();
Map<String,String> tokenMap =  new HashMap<String, String>();

String accessToken = generateAccessToken(appId,"USERTEST");//生成访问令牌access_token的值
tokenScopeMap.put(accessToken,codeScopeMap.get(code));//授权范围与访问令牌绑定

//生成访问令牌的方法
private String generateAccessToken(String appId,String user){
  
  String accessToken = UUID.randomUUID().toString();
  String expires_in = "1";//1天时间过期
  tokenMap.put(accessToken,appId+"|"+user+"|"+System.currentTimeMillis()+"|"+expires_in);

  return accessToken;
}
4.刷新令牌
1. 刷新令牌的生成
	accessToken生成的同时生成refreshToken
2. 刷新令牌 的使用
	1. accessToken失效可使用刷新令牌获取访问权限,这样就不用再次走授权流程
	2. accessToken失效后,refreshToken会生成新的accessToken和refreshToken给第三方软件,更加安全
	还有其他方案:accessToken失效后,refreshToken会延长原accessToken的时间(不建议,不安全)

Map<String,String> refreshTokenMap =  new HashMap<String, String>();

String refreshToken = generateRefreshToken(appId,"USERTEST");//生成刷新令牌refresh_token的值

private String generateRefreshToken(String appId,String user){

  String refreshToken = UUID.randomUUID().toString();

  refreshTokenMap.put(refreshToken,appId+"|"+user+"|"+System.currentTimeMillis());
  return refreshToken;
  
} 	
5.接口

参考:http://t.zoukankan.com/huiy-p-8463557.html

  1. 获取授权码

    …/authorize

    参数:

    ​ response_type:表示授权类型,必选项,此处的值固定为"code

    ​ clien_id:客户端id

    ​ redirect_uri: 重定向地址,可选项

    ​ scope:权限范围,可选

    ​ state:客户端状态,客户端生成,认证服务器原封不动返回

    GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
            &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: server.example.com
    
  2. 认证服务器响应

    code:授权码:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系

    state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数

    HTTP/1.1 302 Found
    Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
              &state=xyz
    
  3. 获取访问令牌

    grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"

    code:表示上一步获得的授权码,必选项。

    client_id:表示客户端ID,必选项。

    client_secret:客户端秘钥

    redirect_uri:表示重定向URI,必选项

    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&client_id=s6BhdRkqt3
    &client_secret=232ddsc&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
    

4.JWT令牌

1. 什么是JWT令牌?

结构化令牌(结构化,加密令牌)

资源服务器计算解密 验证,理念:计算代替存储

2.JWT令牌的结构有哪些?

在这里插入图片描述

HEADER: typ令牌类型,alg加密方式

PAYLOAD:

iat:令牌生成时间

exp:失效时间

sub:用户唯一标识

自定义信息

sign:签名

3.令牌内检

受保护资源服务器 校验令牌的过程就叫做令牌内检

授权服务“扔出”一个令牌,受保护资源服务“接住”这个令牌,然后自己开始解析令牌本身所包含的信息就可以了,而不需要再去查询数据库或者请求 RPC 服务

4. JWT令牌的优缺点
  1. 优点

    1、计算代替存储,减少了 资源服务器查询数据库或者存储文件的时间
    2、加密,安全

  2. 缺点

    JWT一经发放无法更改,只有等待生命周期自动结束
    问题 : JWT有效期间,用户修改了密码怎么办?或者主动取消了授权(类似用户订阅第三方服务到期)怎么办

  3. 改进方案

    1. 将每次生成 JWT 令牌时的秘钥粒度缩小到用户级别,也就是一个用户一个秘钥。当用户取消授权或者修改密码后,就可以让这个密钥一起修改
    2. 在不提供用户主动取消授权的环境里面,我们就可以把用户密码作为 JWT 的密钥
5.令牌的生命周期
  1. 正常使用

  2. 失效后refreshToken刷新

  3. 第三方软件主动失效,比如 用户在第三方软件购买的 服务到期,但是 Token还在有效期

    那就需要 第三方软件主动让token失效

在这里插入图片描述

6. jwt的使用场景
1. 场景
  1. 一次性
    由于jwt有用户标识且有过期时间,那么类似 邮件期限激活 这种场景比较适合jwt

  2. restful api 认证

    客户端和服务端共享 secret;过期时间由服务端校验,客户端定时刷新(也可使用restful token刷新);签名信息不可被修改…spring security oauth jwt 提供了一套完整的 jwt 认证体系

  3. jwt做登录会话+单点登录(不推荐)

  4. 数据交换

2.jwt做会话或者单点登录的问题以及解决方案

jwt 秘钥泄露

​ jwt可以是 非对称加密也可以是 对称加密

​ 建议适应https网络传输

注销/修改密码问题

对于注销和修改密码问题:

​ 1.注销/修改密码时 修改秘钥,使jwt失效,不过需要单独做一个秘钥管理功能

​ 2. 只针对修改密码问题,可以把用户密码做为jwt的秘钥使用

jwt续签问题

1.无状态方案

​ a.每次请求生成不同的 jwt,方案比较暴力

​ b.在上个方案的基础上,服务器检测 jwt,只在最后几分钟生成一个新的jwt

2.有状态方案

​ a.使用refresh token ,允许客户端主动刷新jwt

​ b.redis保存jwt,key为jwt,value,用户信息,、设置超时时间,访问时更新时间

5.oauth2.0其他三种模式

1. 密码模式(资源拥有者模式)

资源拥有者,客户端都是 京东的用户,官方软件

​ 需要客户端有自己的 登录页面

获取accessToken接口参数:

client_id,client_secret, username,password,redirect_uri

适用于 同一体系(比如:统一微服务体系),没有第三方概念的系统

在这里插入图片描述

2. 客户端模式

获取accessToken接口参数:

client_id,client_secret,redirect_uri

场景:资源拥有者不明确,或者没有资源拥有者,不需要 资源拥有者授权(点击授权按钮),比如第三方软件想获取 京东的位置信息,天气信息等非敏感信息

在这里插入图片描述

3.隐私许可模式

场景:第三方没有后端程序,后者后端逻辑集成到 app或浏览器内部的系统

获取accessToken接口参数:

client_id,client_secret,redirect_uri

在这里插入图片描述

4.oauth2.0 四种模式应用场景

授权码:第三方软件授权访问,比如微信/qq授权登录

资源拥有者(密码模式): 适用 内部系统,相互信任的系统(比如微服务内部系统)

客户端模式:适合没有资源拥有者 ,不需要 资源拥有者授权(点击授权按钮),获取非敏感信息

隐式许可:适合没有后端程序的服务

在这里插入图片描述

6.第三方软件构建 & 权限范围

1. 第三方软件构建

a.第三方软件在oauth2.0中做了那些事情

  • 客户端注册(app_id,app_secret,redirect_uri ,scope)

  • 引导用户到授权页面

    String oauthUrl = "http://localhost:8081/OauthServlet-ch03?reqType=oauth";
    
    response.sendRedirect(toOauthUrl);
    
  • 获取accessToken

  • 使用accessToken

    String protectedURl="http://localhost:8082/ProtectedServlet-ch03";
    Map<String, String> paramsMap = new HashMap<String, String>();
    paramsMap.put("app_id","APPID_RABBIT");
    paramsMap.put("app_secret","APPSECRET_RABBIT");
    paramsMap.put("token",accessToken);
    String result = HttpURLClient.doPost(protectedURl,HttpURLClient.mapToStr(paramsMap));
    
  • 使用refreshToken

2.权限范围
  1. 接口权限(web api 接口权限)

    客户端注册时会注册 使用权限,有一个scope,代表客户端所拥有的 web api访问列表

    用户在 授权页面 选择授予客户端 访问部分web api的权限

  2. 数据权限

    比如,有一个查询小明信息的 API,返回的信息包括 Contact(email、phone、qq)、Like(Basketball、Swimming)、Personal Data(sex、age、nickname)。如果小兔软件请求过来的一个访问令牌 access_token 的 scope 权限范围只对应了 Personal Data,那么包含该 access_token 值的请求就不能获取到 Contact 和 Like 的信息

  3. 用户权限

    同一个web api接口 ,不同用户获取数据不一样,不同商家ID只能获取 自己的订单,京东管理员可以查询所有商家订单

二、进阶篇

1. 移动APP 中 使用oauth2.0

​ 移动APP 分为无服务端 和 有服务端

1. PKCE协议

​ PKCE 协议,全称是 Proof Key for Code Exchange by OAuth Public Clients。

a.移动APP无server情况下如何使用 oauth2.0的授权码模式呢?

​ 拿到code后要有server端带上 app_secret 获取 access token ,无server 那么把app_secret
​ 放在用户手机上,由 client端去获取access token,这样是不安全的。

b.PKCE是如何解决安全问题的呢?
本质就是签名验签来解决安全问题。

	  **引入了code_verify(校验码) ,code_challenge(挑战码)code_challenge_method(校验方式)**

​ code_challenge_method 有两个值 plain 和 S256

​ plain: code_verify等于 code_challenge

​ S256: 将 code_verifier 值进行 ASCII 编码之后再进行哈希,然后再将哈希之后的值进行 BASE64-URL 编码

​ 流程:

​ 1.authorize获取code的时候传递 code_challenge和code_challenge_method,授权服务器保存

​ 2. 获取访问token的时候传code_verify,授权服务器 校验成功后返回 access token

 #### 2.移动APP有server	

在这里插入图片描述

2. OIDC协议

1. OIDC协议是什么?

OIDC全拼openId connect ,身份认证协议

OIDC= 授权协议 + 身份认证,OIDC 就是直接基于 OAuth 2.0 构建的身份认证框架协议。

单点登录和联合登录(联合登录也叫授权登录,例如:微信,淘宝授权登录等)都是OIDC实现的。

2.OIDC中的角色

​ EU(End User),代表最终用户。

​ RP(Relying Party),代表认证服务的依赖方,就是上面我提到的第三方软件。

​ OP(OpenID Provider),代表提供身份认证服务方。

3. OIDC 与OAUTH2.0区别

区别就在 ID_TOKEN

4.ID_TOKEN

ID_TOKEN 其实是一个 jwt令牌。

正常设置局部会话:

1. 设置用户信息到cookie,设置过期时间2. 中间件服务器(比如redis)保存token,设置过期时间

但是ID_TOKEN即有 过期时间又有 身份唯一标识,第三方解析ID_TOKEN就可以获取用户信息

从而设置局部会话

第三方软件解析并验证 ID 令牌的合法性之后,不需要将整个 JWT 信息保存下来,只需保留 JWT 中的 PAYLOAD(数据体)部分就可以了。因为正是这部分内容,包含了身份认证所需要的用户唯一标识等信息。

它有以下内容:

  1. iss,令牌的颁发者,其值就是身份认证服务(OP)的 URL。
  2. sub,令牌的主题,其值是一个能够代表最终用户(EU)的全局唯一标识符。
  3. aud,令牌的目标受众,其值是三方软件(RP)的 app_id。
  4. exp,令牌的到期时间戳,所有的 ID 令牌都会有一个过期时间。iat,颁发令牌的时间戳。
//GENATE ID TOKENString id_token=genrateIdToken(appId,user);private String genrateIdToken(String appId,String user){    String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth";//秘钥    Key key = new SecretKeySpec(sharedTokenSecret.getBytes(),            SignatureAlgorithm.HS256.getJcaName());//采用HS256算法    Map<String, Object> headerMap = new HashMap<>();//ID令牌的头部信息    headerMap.put("typ", "JWT");    headerMap.put("alg", "HS256");    Map<String, Object> payloadMap = new HashMap<>();//ID令牌的主体信息    payloadMap.put("iss", "http://localhost:8081/");    payloadMap.put("sub", user);    payloadMap.put("aud", appId);    payloadMap.put("exp", 1584105790703L);    payloadMap.put("iat", 1584105948372L);    return Jwts.builder().setHeaderParams(headerMap).setClaims(payloadMap).signWith(key,SignatureAlgorithm.HS256).compact();}	

3. oauth2.0安全问题

1.CRSF

CSRF : Cross Station Request Forgery ,跨站请求伪造攻击。

恶意攻软件构造非法页面 让浏览器向已登陆认证过的网站发送请求,并执行有害操作 就是跨站请求伪造。

比如:

1.攻击软件A从微信获取授权码codeA,然后构造一个页面 有这样一个链接(地址为受害者软件 授权流程的回调地址)

2.此时,(软件B )极客帮(极客时间)用户已经登录,用户点击上面链接就会 取获取accessToken:

token?code=codeA&appId=appId_B&app_secret = app_secret_b

3.如果授权服务器没有对进行 code绑定的userId和client做校验,就会返回正确accessToken,这个token是被攻击着的code

和userId绑定了 的,,就是用户A,绑定了用户B的accessToken,那么A就可以用B的身份获取B的信息,之心一些违法操作了

解决方案: authorize?app_id&redirect_uri&state,请求获取授权码的时候在请求参数里传递 state来表示客户端(第三方软件)的状态,授权服务器返回 code和state
2.XSS

脚本注入攻击,会注意一些

解决方案:

服务器端做参数验证,过滤

3.水平越权

比如: 访问订单数据的功能,用户A拿着用户B 的订单ID 访问用户B的数据

如果没有做权限验证就会返回用户B的数据给A

针对这种情况可以做权限验证

4.重定向路径被篡改 && 授权码被盗用

针对重定向路径被篡改只需要 修改校验redirect_uri即可

针对授权码被盗用 可以使 code使用一次后立即删除

4.互联网企业是如何使用oauth2.0的?

1.京东开放平台全局体系结构

2.开放平台体系交互示意图

在这里插入图片描述

3.修改密码后使accessToken快速失效

用户修改密码或者注销后,发送此类型消息到MQ,授权服务订阅此消息,清除token信息

5. 微服务架构中的oauth2.0

1. 基于kubernates的微服务架构

常用微服务架构图

1.nginx反向代理层

主要反向路由,将外部流量根据 HOST 主机头或者 PATH,路由到不同的web应用或者网关。

在 Kubernetes 体系中,Nginx 是和 Ingress Controller(入口控制器)配合工作的(总称为 Nginx Ingress),Ingress Controller 支持通过 Ingress Rules,配置 Nginx 的路由规则。

2.web端

主要是一些web应用,一些html/css/js就是在这一层。

Web 服务层通常采用传统的 Web MVC + 模版引擎方式处理,可以实现服务器端渲染,也可以采用单页 SPA 方式。这一层主要由公司的前端团队负责,通常会使用 Node.js 技术栈来实现,也可以采用 Spring MVC 技术栈实现。

当需要调用后端数据服务的时候会经过网关。

3.Gateway 网关层

反向路由,日志监控,熔断限流。

校验令牌:拿着access token 去IDP校验,IDP返回带有用户信息和权限的jwt令牌。

权限校验:获取到jwt可校验 用户权限是否可访问请求的web api。

4.IDP-认证授权

可基于 oauth2.0实现,负责令牌分发,校验,jwt生成,认证授权功能

5.BFF聚合服务

BFF 是 Backend for Frontend 的简称,主要实现对后台领域服务的聚合(Aggregation,有点类似数据库的 Join)功能,同时为不同的前端体验(PC/Mobile/ 开放平台等)提供更友好的 API 和数据格式。

BFF 中可以包含一些业务逻辑,甚至还可以有自己的数据库存储。通常,BFF 要调用两个或两个以上的领域服务,甚至还可能调用其它的 BFF(当然一般并不建议这样调用,因为这样会让调用关系变得错综复杂,无法理解)。

例子: 当有domain svc 1  更新操作,需要domain svc2的某个属性A,为了不破坏领域服务的独立性与无状态性,需要如何设计

解决方案:

a. 使用聚合服务BFF层,BFF1;BFF1先查询 domain svc2的属性A,再调用 domain svc1的更新接口

b. domain svc2的属性A更新是,自动同步更新到其他使用 属性A 的服务

推荐使用a方案,b方案复杂行高,涉及消息同步机制

6.领域服务

微服务的基础与底层,领域服务有独立的数据库,互不调用,互不依赖,独立部署;

比如:用户服务,购物车服务,订单服务

BFF 和 领域服务都是无状态的,他们靠 jwt获取用户信息和权限信息。所以整个架构中微服务都是无状态的,

状态要么存在 jwt,要么在 客户端浏览器,手机APP,要么在数据库中存储

2.登录场景
  • 第一方web登录+资源拥有着模式

  • 第一方移动APP登录+授权码模式+PKCE协议

  • 第三方登录+授权码模式

    1. 访问流程

3.注意问题

IDP 需要实现access token 转 jwt的功能;

IDP的部署方式

1. 独立在gateway网关之外,直接在nginx后面
2. 登录页 放在nginx,web api 放在gateway之后
3. 完全放在 gateway之后

SSO时 IDP要支持session保存用户登录状态(全局会话),cookie写入浏览器,建议写入根域名,集群时可做

session共享;

SPA单页登录

​ 如果浏览器支持 Web Crypto for PKCE,可以使用 PKCE协议+授权码模式的登录方式,走“第一方移动应用”

​ 否则,考虑 SPA+ 传统 Web 混合(hybrid)模式,前端页面可以住在客户浏览器端中,但登录认证还是由后台 Web 站点配合实现,走类似“第一方 Web 应用”场景的资源拥有者凭据模式,或者“第三方 Web 应用”场景下的授权码许可模式。

三、其他

1. 保持会话策略

  1. cookie

    用户信息存在浏览器上,浏览器访问服务的时候会自动带上cookie

  2. session

    存在服务器上,返回JSessionId 给浏览器cookie;

    弊端 占用服务器内存

  3. ip_hash

    根据host_ip 分发到 认证服务器集群,保证同一个客户端ip分发到同一个服务器

  4. 共享session

    session集中保存,比如保存到redis中

    但是,每次都要查一下redis ,进行redis服务器连接,这样是花销,

    如果对性能有极致的要求可以考虑使用Spring Session

    Spring Session

    ​ 服务器把cookie写入根域名或者二级域名 , 子域就可以携带 cookie(要保证系统服务群的根域名或者子域名)

2.开放平台 web api设计

1.webapi设计

一般有这几方面考虑因素: 安全认证,时效性,内容防篡改,防重复提交

安全认证: 可以通过签名实现,md5,rsa等都行,但要保护好秘钥;一般需要token机制时,需要分两次请求(第一次拿app_id,app_secret获取token,

第二次拿token调用接口)

时效性:传入timestamp参数

内容防篡改:除sign之外的签名排序,然后使用签名算法签名

防重复提交:传入随机参数nonce,放入redis缓存,并设置过期时间,单位时间内重复提交,如果nonce存在就拒绝请求

appKey 接口Key
appSecret 接口密钥
timeStamp 时间戳 毫秒
nonceStr 随机字符串
signature 加密字符串
2. 超高安全级别案例

RSA+AES 实现接口签名,请求加密

接口调用方

​ a. AES对业务参数加密

​ b. RSA公钥对AES秘钥加密

​ c.RSA私钥对 请求参数签名

请求和接收的实体对象

@Data
public class JsonRequest {
    //接口id 可空
    private String serviceId;
    //请求唯一id 非空
    private String requestId;
    //商户id 非空
    private String appId;
    //参数签名 非空
    private String sign;
    //对称加密key 非空
    private String aseKey;
    //时间戳,精确到毫秒 非空
    private long timestamp;
    //请求的业务参数(AES加密后传入) 可空
    private String body;
}
  • serviceId:服务id(接口id)。接口设计分为两种,一种是所有的调用方针对类似的业务,都调用的是同一接口地址,然后内部系统根据serviceId去判断具体是要调用哪个业务方法;另一种是针对不同的调用方,开发不同的接口,接口地址也是不一样,那么这个时候就可以不要serviceId这个字段。本章是使用第二种方式,所以serviceId可以不要(可空)。
  • requestId:请求唯一id。方便查询定位某个请求和防止同个请求多次调用。
  • appId:商户id,即我们会给调用方分配一个这样的id,并且将这个id与调用方的信息进行关联,比如“通过appId查询出调用方的加密密钥等”
  • aseKey:是AES对称加密的密钥。用于解密业务请求参数。这里要先用RSA公钥对aseKey进行加密后传输。
  • timestamp:请求时间戳。可以用该字段,对请求的时间合法性进行校验。(如:过滤掉请求时间不在当前时间的正负10分钟范围内的请求)
  • body:请求的业务参数。对请求的业务参数AES加密后再赋值。
3.RSA加密和签名的区别
  1. 加解密过程简述
    A和B进行通信加密,B要先生成一对RSA密钥,B自己持有私钥,给A公钥 —>A使用B的公钥加密要发送的内容,然后B接收到密文后通过自己的私钥解密内容

  2. 签名验签过程简述
    A给B发送消息,A先计算出消息的消息摘要,然后使用自己的私钥加密消息摘要,被加密的消息摘要就是签名.(A用自己的私钥给消息摘要加密成为签名)
    B收到消息后,也会使用和A相同的方法提取消息摘要,然后用A的公钥解密签名,并与自己计算出来的消息摘要进行比较–>如果相同则说明消息是A发送给B的,同时,A也无法否认自己发送消息给B的事实.(B使用A的公钥解密签名文件的过程,叫做"验签").

    参考:RSA算法

    ​ [AES+RSA web api接口交互](

四、思维脑图

FAQ

参考

阮一峰-OAuth 2.0的设计思路和运行流程:http://t.zoukankan.com/huiy-p-8463557.html

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值