卖烤红薯也要懂OAuth2.0

点击上方“程序人生”,选择“置顶公众号”

第一时间关注程序猿(媛)身边的故事


640?题图 | @peixi

作者

寒食君i

已获原作者授权,如需转载,请联系原作者。


小季临近毕业了,但是他听说最近经济形势不太好,消费降级成为了一个热议的话题。和他最直接相关的就是各大互联网公司缩招了,本身就技术平平的他,这下更为找工作发愁了。

小季刚出校园,对经济理论这些不甚了解,这一时半会也找不到互联网开发相关的岗位,竟有点束手无策了。不过他对信息还是有一定的敏感度,由于大家现在普遍比较穷,很多人不得消费低价的商品。

640?

所以网络上出现了一句:“吃着涪陵榨菜,喝着二锅头,出门共享单车,购物拼夕夕。”小季心想,做事情还是得顺势而为,不要老想着逆天。俗话说:上大学不如卖红薯。烤红薯作为典型的快消品,这是妥妥的商机啊。

几年过去了,小季变成了中等季。而他的「初恋红薯」也已经在全世界开了100000家连锁,slogan就是「捧在手心,化在口中」。生意做这么大,当然是有独家研制的配方,传闻是这个配方是小季用机器学习训练出来的。

那么问题来了,如何保证独家配方能安全的到达每个门店?小季基于以前学过的OAuth2.0,设计了一个鉴权的流程。

由于全世界门店太多,我们现在和一些第三方的物流中心合作。这些物流中心必须是在「初恋红薯」注册审核过的,才会拥有配送的资格。

上海这一片的配送服务是由一家名为「字节物流」的公司承包的(公众号「字节流」旗下物流公司)。下面我们将角色捋一捋。

门店 = 用户;

秘制原料 = 用户数据;

物流公司 = 第三方;

总部 = 数据拥有方

现在上海一家门店S需要通过「字节物流」Z向总部拿原料。

如果是最传统的方式,S把自己的账号密码交给Z,Z把S的账号密码带到总部请求验证。这样就会产生一个问题:假如Z保存了S的账号密码,在S不知情的情况下去骗取原料呢?而S要频繁地修改密码才能防止这个行为,这很麻烦,且不安全。

现在小季基于OAuth2.0设计的方式是这样的:

640?

640?

640?

完成服务后,只要access_token失效,第三方则无法访问数据中心。

那么,到底什么是OAuth?

640?

维基百科给出了这样的解释:

640?

开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。

在越来越开放的互联网世界,这是一种常用的授权方式,有效地连接和隔离了系统。

比如我们平时在使用第三方APP或第三方网站时,常常可以使用微信登录,这是微信开放平台给予了第三方的开发者权限,微信的登录权限也是基于OAuth2.0的。下面我们通过一个demo,来了解一下微信登录的流程,可以结合对比「初恋红薯」的例子。

现在我们有一个自己开发的网站,为了给予用户更好的体验,允许用户使用微信登录,而不需要立刻注册账号。

首先我们需要请求微信的授权:


 
  1. https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

我对其中的几个重要参数具体解释一下:

  1. appid=APPID,APPID是第三方开发者在微信开放平台上注册应用ID

  2. redirect_uri=REDIRECT_URI,若用户同意授权,则回调REDIRECT_URI这个接口,这个接口是开发者部署在自己的服务器上的,用于接受返回的code,并利用code做进一步处理。

  3. response_type、 scope、 state是微信规定的返回类型、权限域、状态,代表了需要请求的资源的种类、适用范围等。具体可以参考微信开放平台的官方文档。

上述参数中,最需要开发者关注的是回调接口,这个需要我们自己编写,以继续后续的操作。下面我用一段简易的Java代码来演示:


 
  1. // 对外接口

  2. @RequestMapping(path = "/user", method = RequestMethod.GET)

  3.  public ResponseEntity<?> wxcall(@RequestParam(value = "code", required = false) String code,

  4.                                  HttpServletResponse response) {

  5.        User user = weixinService.getWxUserInfo(code);

  6.    }


 
  1. // 根据code获取access_token 和 openid

  2. public User getWxUserInfo(String code) {

  3.    JsonParser parser = new JsonParser();

  4.    String uri = UriComponentsBuilder

  5.      .fromHttpUrl("https://api.weixin.qq.com/sns/oauth2/access_token")

  6.      .queryParam("appid", WeixinConstants.APPID )

  7.      .queryParam("secret", WeixinConstants.APPSECRET)

  8.      .queryParam("code", code)

  9.      .queryParam("grant_type", "authorization_code")

  10.      .toUriString();

  11.    HttpEntity<String> response = templateProvider.getRestTemplate()

  12.      .exchange(uri, HttpMethod.GET, null, String.class);

  13.    JsonObject accessTokenJson = null;

  14.    try {

  15.      accessTokenJson = parser.parse(response.getBody()).getAsJsonObject();

  16.    } catch (Exception e) {

  17.      e.printStackTrace();

  18.    }

  19.    if (accessTokenJson == null || !accessTokenJson.has("access_token")) {

  20.      logger.error("fetch accesstoken error {}", response.getBody());

  21.      return null;

  22.    }

  23. // 获取 用户信息

  24.    String infoUri = UriComponentsBuilder

  25.      .fromHttpUrl("https://api.weixin.qq.com/sns/userinfo")

  26.      .queryParam("access_token", accessTokenJson.get("access_token").getAsString())

  27.      .queryParam("openid", accessTokenJson.get("openid").getAsString())

  28.      .queryParam("lang", "zh_CN")

  29.      .toUriString();

  30.    HttpEntity<String> userInfo = templateProvider.getRestTemplate()

  31.      .exchange(infoUri, HttpMethod.GET, null, String.class);

  32.    JsonObject userInfoJson = null;

  33.    try {

  34.      userInfoJson = parser.parse(userInfo.getBody()).getAsJsonObject();

  35.    } catch (Exception e) {

  36.      e.printStackTrace();

  37.    }

  38.    if (userInfoJson == null ||

  39.      (userInfoJson.has("errcode") && userInfoJson.get("errcode").getAsInt() != 0)) {

  40.      logger.error("fetch userinfo error {}", userInfo.getBody());

  41.      return null;

  42.    }

此时,用户的基本信息已经封装在了userInfoJson中,可以享用了。

这样一来,「初恋红薯」的秘制原料就能在可控安全的范围内运输使用了。小季步入中年,看着自己的连锁店在神州大地上星罗棋布,不禁露出了优雅的成功中年男人の微笑。

突然,室友摇醒了梦中的小季。“快醒醒!你的邮箱里收到offer啦!”小季这才惊觉原来是南柯一梦,打开邮箱,邮件上赫然写着:月薪4k包吃住。

640?



- The End -

「若你有原创文章想与大家分享,欢迎投稿。」

加编辑微信ID,备注#投稿#:

程序 丨 druidlost  

小七 丨 duoshangshuang


点文末阅读全文,看『程序人生』其他精彩文章推荐。


推荐阅读:

640?wx_fmt=gif

print_r('点个赞吧');
var_dump('点个赞吧');
NSLog(@"点个赞吧!")
System.out.println("点个赞吧!");
console.log("点个赞吧!");
print("点个赞吧!");
printf("点个赞吧!\n");
cout << "点个赞吧!" << endl;
Console.WriteLine("点个赞吧!");
fmt.Println("点个赞吧!")
Response.Write("点个赞吧");
alert(’点个赞吧’)
标题基于SpringBoot+Vue的社区便民服务平台研究AI更换标题第1章引言介绍社区便民服务平台的研究背景、意义,以及基于SpringBoot+Vue技术的研究现状和创新点。1.1研究背景与意义分析社区便民服务的重要性,以及SpringBoot+Vue技术在平台建设中的优势。1.2国内外研究现状概述国内外在社区便民服务平台方面的发展现状。1.3研究方法与创新点阐述本文采用的研究方法和在SpringBoot+Vue技术应用上的创新之处。第2章相关理论介绍SpringBoot和Vue的相关理论基础,以及它们在社区便民服务平台中的应用。2.1SpringBoot技术概述解释SpringBoot的基本概念、特点及其在便民服务平台中的应用价值。2.2Vue技术概述阐述Vue的核心思想、技术特性及其在前端界面开发中的优势。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue如何有效整合,以提升社区便民服务平台的性能。第3章平台需求分析与设计分析社区便民服务平台的需求,并基于SpringBoot+Vue技术进行平台设计。3.1需求分析明确平台需满足的功能需求和性能需求。3.2架构设计设计平台的整体架构,包括前后端分离、模块化设计等思想。3.3数据库设计根据平台需求设计合理的数据库结构,包括数据表、字段等。第4章平台实现与关键技术详细阐述基于SpringBoot+Vue的社区便民服务平台的实现过程及关键技术。4.1后端服务实现使用SpringBoot实现后端服务,包括用户管理、服务管理等核心功能。4.2前端界面实现采用Vue技术实现前端界面,提供友好的用户交互体验。4.3前后端交互技术探讨前后端数据交互的方式,如RESTful API、WebSocket等。第5章平台测试与优化对实现的社区便民服务平台进行全面测试,并针对问题进行优化。5.1测试环境与工具介绍测试
资源下载链接为: https://pan.quark.cn/s/9648a1f24758 Java中将Word文档转换为PDF是一种常见的技术需求,尤其在跨平台共享、保持格式一致性和便于在线预览等场景中非常实用。通常,开发者会借助专门的库来实现这一功能,其中Aspose.Words是一个非常强大的选择。Aspose.Words是由Aspose公司开发的文档处理组件,支持多种文件格式,包括Word和PDF。它提供了丰富的API,方便开发者在Java应用程序中进行文件转换、编辑和格式化操作,尤其在Word转PDF方面表现卓越。 使用Aspose.Words进行Word转PDF的步骤如下: 添加依赖:通过Maven或Gradle等工具将Aspose.Words的Java库引入项目。 加载Word文档:使用Document类加载Word文件,例如: 配置输出选项:创建PdfSaveOptions对象,用于设置PDF保存时的选项,如图像质量、安全性等。 执行转换:调用Document的save方法,传入输出路径和PdfSaveOptions对象,例如: 支持多种输出格式:Aspose.Words不仅支持将Word转换为PDF,还能转换为HTML、EPUB、XPS等多种格式,只需更换SaveOptions的子类即可。 保持格式与样式:在转换过程中,Aspose.Words能够最大程度地保留源文档的格式和样式,包括文本样式、图像位置、表格布局等。 优化性能:Aspose.Words支持并行处理和多线程技术,可以显著提高大量文档转换的速度。 处理复杂文档:它能够处理包含宏、复杂公式、图表、脚注等元素的Word文档,确保转换后的PDF内容完整且可读。 安全性与版权:在转换过程中,可以设置PDF的访问权限,例如禁止打印或复制文本,从而保护文档内容。 在实际开发中,还需要注意错误和异常的处理,以
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值