关于oauth:关于-OAuth-你又了解哪些

作者罗锦华,API7.ai 技术专家/技术工程师,开源我的项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。OAuth 的背景OAuth,O 是 Open,Auth 是受权,也就是凋谢受权的意思。OAuth 始于 2006 年,其设计初衷正是委托受权,就是让最终用户也就是资源拥有者,将他们在受爱护资源服务器上的局部权限(例如查问当天订单)委托给第三方利用,使得第三方利用可能代表最终用户执行操作(查问当天订单)。 OAuth 1.0 协定于 2010 年 4 月作为 RFC 5849 公布,这是一份信息性的评论申请。OAuth 2.0 框架的公布思考了从更宽泛的 IETF 社区收集的其余用例和可扩展性要求。只管基于 OAuth 1.0 部署体验构建,OAuth 2.0 并不向后兼容 OAuth 1.0。OAuth 2.0 于 2012 年 10 月作为 RFC 6749 公布,承载令牌应用作为 RFC 6750 公布。 在 OAuth 协定中,通过为每个第三方软件和每个用户的组合别离生成对受爱护资源具备受限的拜访权限的凭据,也就是拜访令牌,来代替之前的用户名和明码。而生成拜访令牌之前的登录操作,又是在用户跟平台之间进行的,第三方软件基本无从得悉用户的任何信息。 这样第三方软件的逻辑解决就大大简化了,它今后的动作就变成了申请拜访令牌、应用拜访令牌、拜访受爱护资源,同时在第三方软件调用大量 API 的时候,不再传输用户名和明码,从而缩小了网络安全的攻击面。 说白了就是集中受权。 值得注意的是,OAuth 并非身份验证,这里的 Auth 是 Authorization,OAuth 是产生在用户做了身份验证后的事件,零碎受权用户能做什么操作。互联网中所有的受爱护资源,简直都是以 Web API 的模式来提供拜访的。不同的用户能做的事件不同,例如一个 GitHub 我的项目,有些用户只有读取和提交 PR(pull request)的权限,而管理员用户则能合并 PR。将用户权限在 API 层面细分,是 OAuth 要做的事件。 ...

February 10, 2023 · 2 min · jiezi

关于oauth:OAuth-20-协议学习笔记

协定官网 在传统的客户端-服务器身份验证模型中,客户端通过应用资源所有者的凭据向服务器进行身份验证来申请服务器上的拜访受限资源(受爱护资源)。 为了向第三方应用程序提供对受限资源的拜访,资源所有者与第三方共享其凭证。这产生了若干问题和限度。 第三方应用程序须要存储资源所有者的凭据以备未来应用,通常是明文明码。要求服务器反对明码认证,只管明码存在固有的平安弱点。第三方应用程序取得对资源所有者受爱护资源的过于宽泛的拜访权限,使资源所有者无奈限度持续时间或拜访无限的资源子集。资源所有者不能在不撤销对所有第三方的拜访权限的状况下撤销对单个第三方的拜访权限,必须通过更改第三方的明码来实现。任何第三方应用程序的泄露都会导致最终用户的明码和受该密码保护的所有数据泄露。OAuth 通过引入受权层(authorization layer)并将客户端的角色与资源所有者的角色离开来解决这些问题。在 OAuth 中,客户端申请拜访由资源所有者管制并由资源服务器托管的资源,并取得一组与资源所有者不同的凭据(credentials)。 客户端不是应用资源所有者的凭据来拜访受爱护的资源,而是获取拜访令牌——一个示意特定范畴(scope)、生命周期和其余拜访属性的字符串。拜访令牌由受权服务器(authorization server)在资源所有者的批准下颁发给第三方客户端。客户端应用拜访令牌拜访由资源服务器托管的受爱护资源。 例如,最终用户(资源所有者)能够授予打印服务(客户端)拜访其存储在照片共享服务(资源服务器)中的受爱护照片的权限,而无需与打印服务共享其用户名和明码。相同,她间接向照片共享服务(受权服务器)信赖的服务器进行身份验证,该服务器颁发打印服务委托特定的凭据(拜访令牌)。 该标准设计用于 HTTP ([RFC2616])。 OAuth 1.0 协定 ([RFC5849]) 作为信息文档公布,是小型长期社区致力的后果。此规范跟踪标准建设在 OAuth 1.0 部署教训以及从更宽泛的 IETF 社区收集的其余用例和可扩展性要求的根底上。 OAuth 2.0 协定不向后兼容 OAuth 1.0。这两个版本能够在网络上共存,并且实现能够抉择同时反对这两个版本。然而,本标准的用意是新实现反对本文档中指定的 OAuth 2.0,并且 OAuth 1.0 仅用于反对现有部署。 OAuth 2.0 协定与 OAuth 1.0 协定共享很少的实现细节。相熟 OAuth 1.0 的实施者应该靠近本文档,不要对其构造和细节做任何假如。 Oauth 里的四个角色资源所有者可能授予对受爱护资源的拜访权限的实体。 当资源所有者是集体时,它被称为最终用户。 资源服务器托管受爱护资源的服务器,可能应用拜访令牌承受和响应受爱护资源申请。 # 客户 - client 代表资源所有者并经其受权收回受爱护资源申请的应用程序。术语“客户端”并不意味着任何特定的实现特色(例如,应用程序是否在服务器、桌面或其余设施上执行)。 受权服务器(authorization server)服务器在胜利验证资源所有者并取得受权后向客户端颁发拜访令牌。 受权服务器和资源服务器之间的交互超出了本标准的范畴。 受权服务器能够是与资源服务器雷同的服务器,也能够是独自的实体。 单个受权服务器能够公布多个资源服务器承受的拜访令牌。 形象的 OAuth 2.0 流程形容了四个角色之间的交互,包含以下步骤: (A) 客户端向资源所有者申请受权。 受权申请能够间接发送给资源所有者,或者最好通过受权服务器作为中介间接发送。 (B) 客户端收到受权确认,这是代表资源所有者受权的凭证,应用本标准中定义的四种受权类型之一或应用扩大受权类型示意。受权受权类型取决于客户端申请受权的办法和受权服务器反对的类型。 (C) 客户端申请拜访令牌,这是通过与受权服务器进行身份验证来实现。 (D) 受权服务器对客户端进行身份验证并验证受权许可,如果无效,则颁发拜访令牌。 ...

August 7, 2021 · 1 min · jiezi

关于oauth:前后端分离项目OAuth第三方登录怎么做以Github举例

OAuth是一种受权机制。OAuth过程中,零碎会询问数据所有者,是否批准受权第三方利用进入零碎获取这些数据,批准,则零碎将产生一个短期的进入令牌(token),用来代替明码,供第三方利用应用。 # OAuth流程(假如你的站点是A网站)1. 用户事件触发(个别点击事件)跳转,到 Github2. Github 要求用户登录,并询问用户是批准 Github 下放受权码给 A 网站3. 用户批准,则 Github 重定向到 A 网站,同时携带一个受权码(code,以url拼接模式下放)4. A 网站应用受权码(code)向 Github 申请令牌(token)5. Github 返回令牌(token)6. A 网站应用令牌,向 Github 申请用户数据7. A 网站获得用户 Github 数据,前端展现登陆,后端存储更新用户数据,并记录登录状态    本示例中,我的项目前后端拆散开发,前端采纳大家熟知的vue,后端采纳koa2,OAuth逻辑和前后端框架其实无关,只会因为前后端拆散在写法和前后端不拆散我的项目上略有不同。上面别离来说说进行OAuth开发前做的筹备,以及在前后端我的项目中如何编写代码。 一、配置Github 链接:https://github.com/settings/a... Application name:站点名称,这里假如是a Homepage URL: 主站链接,本地测试,这里是localhost:8001 Authorization callback URL:Github重定向链接,本地测试,这里是localhost:8001/login 确认后,github将生成OAuth所须要的 clientID 和  clientSecret 二、前端编写 // 将登录办法封装为插件 oauth.jsconst getQuery = require('./getQuery') // 集体编写用来获取url query的办法const oauthGithub = { getCode() { const authorize_uri = 'https://github.com/login/oauth/authorize'; const client_id = 'b82f7274e2e996a2cecc'; const redirect_uri = 'http://localhost:8001/login'; location.href = `${authorize_uri}?client_id=${client_id}&redirect_uri=${redirect_uri}`; }, async getUser(_this) { const code = getQuery('code'); if (code) { try { const res = await _this.$axios.post(`/api/oauth/github?code=${code}`); if (res.data.errorno) { _this.$root.$emit('toast', { variant: 'danger', text: '登录失败' }); // 自定义toast } else { _this.$store.commit('setUser', res.data.data); // 存储用户数据 _this.$root.$emit('toast', { variant: 'success', text: '登录胜利' }); } } catch(err) { _this.$root.$emit('toast', { variant: 'danger', text: '登录失败' }); } } }}module.exports = { oauthGithub}// 在页面或组件内调用插件办法<template> <b-card> <b-row> <b-col md="4" class="border-right"> <h5 class="pb-2 text-center">第三方登录</h5> <div class="flex justify-center"> <div class="pointer hover" @click="getCode()"> <b-icon icon="github" font-scale="3"></b-icon> <p class="m-0 p-0">Github</p> </div> </div> </b-col> </b-row> </b-card></template><script> import { oauthGithub } from '~/plugins/oauth' export default { name: 'login', data() { return {} }, mounted() { oauthGithub.getUser(this); // Github下放code重定向后调用 }, methods: { getCode() { oauthGithub.getCode(); // 点击事件触发,获取code } } }</script>二、后端编写 ...

August 5, 2021 · 2 min · jiezi

关于oauth:为什么-OAuth-里除了-Access-Token-之外还需要-Refresh-Token

What is the purpose of a “Refresh Token”? 问题:我有一个与 YouTube Live Streaming API 集成的程序。我以每 50 分钟的工夫距离,应用刷新令牌(refresh token)获取一个新的拜访令牌(Access Token)。 我的问题是,为什么 OAuth 要设计双重 token? 当我通过 YouTube 进行身份验证时,它给了我一个刷新令牌。而后我应用这个刷新令牌大概每小时获取一个新的拜访令牌。 如果我有刷新令牌,我总是能够应用它来获取新的拜访令牌,因为它永远不会过期。所以我不认为这比从一开始就给我一个拜访令牌更平安。 答复简略地说,刷新令牌用于获取新的拜访令牌。 为了分明地区分这两个令牌并防止混同,以下是 OAuth 2.0 受权框架中给出的性能: 拜访令牌由受权服务器在资源所有者的批准下颁发给第三方客户端。客户端应用拜访令牌拜访由资源服务器托管的受爱护资源。刷新令牌是用于获取拜访令牌的凭据。刷新令牌由受权服务器颁发给客户端,用于在以后拜访令牌生效或过期时获取新的拜访令牌,或者获取具备雷同或更窄范畴的附加拜访令牌。出于平安起因,refresh_token 只与受权服务器替换,而 access_token 与资源服务器替换。这升高了“拜访令牌有效期为一小时,刷新令牌有效期为一年或撤销前无效”与“拜访令牌无效直至撤销而无需刷新”中长期存在的 access_token 透露的危险。 刷新令牌至多有两个用处。首先,刷新令牌是一种“证实”,表明 OAuth2 客户端曾经从用户那里取得了拜访其数据的许可,因而能够再次申请新的拜访令牌,而无需用户通过整个 OAuth2 流程。其次,与长期拜访令牌相比,它有助于减少整个平安流程。 刷新令牌作为不影响用户体验的一种形式让咱们用一个例子来谈谈第一个目标。假如您是一名用户,正在应用想要与您的 YouTube 帐户数据进行交互的第三方客户端网络应用程序。一旦您授予客户端应用程序应用您的 YouTube 数据的权限,您是否心愿客户端应用程序在其 YouTube 令牌过期时再次提醒您取得许可?如果 YouTube 令牌到期工夫十分短(例如 5 分钟),会产生什么? 如果客户端应用程序至多每 5 分钟提醒您一次许可,那会有点烦人! OAuth2 针对这个“问题”提出的解决方案是刷新令牌。通过应用刷新令牌,拜访令牌能够放弃短暂的生命周期(这在拜访令牌以某种形式泄露或被盗的状况下是可取的),并且刷新令牌能够放弃长期(更)生命周期,从而容许客户端取得新的拜访权限令牌过期时无需用户再次许可。 然而为什么要刷新令牌呢?如果重点是不让用户应用权限申请,那么为什么客户端不能简略地说“嘿,受权服务器,我想要另一个拜访令牌。而是,“嘿受权服务器,这是我过期的令牌,给我一个新的!”。刷新令牌作为一种“证实”,证实客户端在某个原始工夫点被用户授予拜访权限。该“证实”采纳由受权服务器数字签名的刷新令牌的模式。通过客户端提供刷新令牌,受权服务器能够验证客户端在过来的某个工夫点收到了用户的许可,并且客户端不用再次提醒用户。 刷新令牌作为进步安全性的一种伎俩然而,这提出了一个问题,“好吧,如果刷新令牌被泄露或被盗,或者只是被歹意客户端应用程序保留而没有应用户的要求将其删除,会产生什么?攻击者能不能持续应用刷新令牌无限期地(或直到它过期)取得无效的拜访令牌?这个问题导致探讨我提到的第二个目标,刷新令牌有助于更平安的流程。 拜访令牌呈现的问题是,一旦取得,它们只会出现给资源服务器(例如 YouTube)。因而,如果拜访令牌被盗或泄露,您如何通知资源服务器不要信赖该令牌?好吧,你真的不能。惟一的办法是更改受权服务器上的公有签名密钥(首先对令牌进行签名的密钥)。 另一方面,刷新令牌须要频繁地提交给受权服务器,因而如果一个令牌被泄露,那么撤销或回绝整个刷新令牌是微不足道的,而不用更改任何签名密钥。 access token (the one that expires soonest) is stored in local storagerefresh token only stored in memory for security reasonsthat is why if you refresh after first time period, you have to log in ...

July 27, 2021 · 1 min · jiezi

关于oauth:SAP系统和微信集成的系列教程之六如何通过OAuth2获取微信用户信息并显示在SAP-UI5应用中

这是Jerry 2020年的第87篇文章,也是汪子熙公众号总共第269篇原创文章。 本系列的英文版Jerry写作于2017年,这个教程总共蕴含十篇文章,发表在SAP社区上。 系列目录(1) 微信开发环境的搭建 (2) 如何通过微信公众号生产API (3) 微信用户关注公众号之后,主动在SAP C4C零碎创立客户主数据 (4) 如何将SAP C4C主数据变动推送给微信公众号 (5) 如何将SAP UI5利用嵌入到微信公众号菜单中 (6) 如何通过OAuth2获取微信用户信息并显示在SAP UI5利用中(本文) (7) 应用Redis存储微信用户和公众号的对话记录 (8) 微信公众号的地图集成 (9) 如何将微信用户发送到微信公众号的音讯保留到SAP C4C零碎 (10) 如何在SAP C4C零碎间接回复音讯给微信公众号的订阅者 最近有不少敌人在微信上向我征询SAP零碎和微信公众号集成的问题,因而我把过后写的英文版翻译成中文,从新公布在我的公众号上。 须要留神的是,时隔三年,微信公众号的开发流程可能有所变动,请大家自行甄别。和微信公众号集成的零碎,我三年前抉择的是SAP Cloud for Customer. 这个系列的第五篇文章,咱们曾经将一个SAP UI5利用绑定到了微信公众号的一个菜单上。点击该菜单,该SAP UI5利用就会在微信app嵌入的浏览器里关上并运行。 本文咱们更进一步,在关上的SAP UI5利用里,显示一些点击了该公众号菜单的微信用户的个人信息,比方微信昵称。 看一个例子:假如Jerry本人的集体微信号昵称为null:(这个昵称高居被前端工程师吐槽的用户昵称排名之首,起因大家都懂的) 当我关注了测试微信公众号,点击公众号菜单关上SAP UI5利用后,我发现自己的微信昵称,null,呈现在了SAP UI5利用的某个字段里: 本文余下局部,会详述这个场景的实现步骤。 在微信公众号后盾开发核心的文档区域里,点击“网页受权获取用户根本信息”,即可查看微信的官网文档: 官网文档提到,如果用户在微信客户端中拜访第三方网页(比方拜访咱们自行开发且部署在某云平台上的SAP UI5利用),并且该第三方利用会调用API获取微信用户个人信息时,公众号须要遵循微信定义的OAuth2 网页受权机制,即须要用户在微信app里手动点击“确认登录”之后,能力容许第三方利用调用微信API,获取以后登录用户的个人信息。 从用户的视角登程,其感知到的流程如下: (1) 用户试图在微信app里通过微信公众号菜单拜访第三方利用。(2) 在微信app里,用户看到微信登录的对话框,蕴含文字“网页由该公众号开发,请确认受权以下信息”和一个“确认登录”的按钮。(3) 用户点击“确认登录”之后,看到了本人想拜访的第三方利用,且该利用页面上显示了本人的微信个人信息比方昵称字段。 以上三个步骤,背地其实产生了很多事件,也须要开发人员对应的编程去实现。 我认为用倒序的形式解说这三个流程中产生的事件,大家会比拟容易了解一些。 在步骤三里,第三方利用调用API获取用户微信昵称时,须要网页受权Access Token,该Token和一般的Access Token并不是一回事,二者获取形式也有差别: 一般的Access Token的获取和应用形式,在Jerry这个系列之前的文章曾经介绍过,通过微信公众号的app id和app secret去换取即可,这里不再反复。 ...

January 6, 2021 · 1 min · jiezi

在Spring-Boot中使用OAuth2保护REST服务

解释OAuth2技术正如我所说,我们将使用OAuth2协议,因此首先要解释这个协议是如何工作的。OAuth2有一些变体,但我将解释我将在程序中使用的内容,为此,我将给你一个例子,以便你了解我们打算做什么。举个例子,在商店里用信用卡付款。在这种场景下,有三个角色:商店、银行和我们。OAuth2协议中也发生了类似的事情,就像这样:1.客户或买方需要银行提供信用卡。然后,银行将收集我们的信息,核实我们是谁,并根据我们帐户中的资金向我们提供信用卡或者直接拒绝我们。在授予卡的OAuth2协议中,它称为身份验证服务器。2.如果银行给了我们卡,我们可以去商店,即网络服务器,我们提供信用卡。商店不欠我们任何东西,但他们可以通过读卡器向银行询问他们是否可以信任我们以及信用余额(信用余额)。商店是资源服务器。3.商店,根据银行说我们拥有的钱,将允许我们购买。在OAuth2类比中,Web服务器将允许我们访问页面,具体取决于我们的财务状况。如果您没有注意到通常使用身份验证服务器,当您转到网页并被要求注册时,它允许您通过Facebook或Google进行。Facebook或Google成为发行“卡”的“银行”,并会验证您的“信用”是否足够支付这个商品。您可以看到“El Pais”的网站并创建一个帐户。如果我们使用Google或Facebook,这个商店将依赖这些身份验证提供商提供的客户身份信息。在这种情况下,网站唯一需要的是拥有信用卡 - 无论余额如何创建授权服务器现在,让我们看看如何创建银行、商店以及您需要的所有其他内容。首先,在我们的项目中,我们需要具有适当的依赖关系。我们需要启动者:Cloud OAuth2,Security和Web。那么,让我们从定义银行开始; 这就是我们之前说的:  AuthorizationServerConfiguration:我们从 @ Configuration 标签开始,然后使用  @EnableAuthorizationServer 标记告诉Spring激活授权服务器。要定义服务器属性,我们指定我们的类扩展  AuthorizationServerConfigurerAdapter,实现了  AuthorizationServerConfigurerAdapter接口,所以Spring将使用这个类来参数化服务器。我们定义了一个Spring自动提供的AuthenticationManager ,我们将使用它来收集@Autowired标签。我们还定义了一个  TokenStore对象,作为public的功能 。 虽然 AuthenticationManager由Spring提供的,但我们必须自己配置它。我等等解释要如何完成这个配置。TokenStore或者IdentifierStore是身份验证服务器提供的标识符将存储的位置,因此当资源服务器(商店)要求信用卡上的信息时,身份验证服务器就要响应它。在这种情况下,我们使用  InMemoryTokenStore将标识符存储在内存中的类。在实际应用中,我们可以使用JdbcTokenStore将它们保存在数据库中,以便在应用程序发生故障时,客户端不必更新其信用卡。在功能配置中 (ClientDetailsServiceConfigurer clients),我们指定银行的凭证,包括身份验证的管理员,以及提供的服务。因为要访问银行,我们必须为每个提供的服务提供用户名和密码。这是一个非常重要的概念:用户名和密码来自银行,而不是客户。对于银行提供的每项服务,将进行单一认证,但对于不同的服务可能相同。我将详细说明这些内容: clients.inMemory ()指定我们将服务存储在内存中。在“真正的”应用程序中,我们将其保存在数据库,LDAP服务器等中。 withClient ("client")是我们将在银行中识别的用户。在这种情况下,它将被称为“客户端”。将他称为“用户”会不会更好? 要  uthorizedGrantTypes ("password", "authorization_code", "refresh_token", "implicit") ,我们指定配置定义的用户,对服务“ 客户端 ”。在我们的示例中,我们将仅使用密码服务。 authorities ("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT", "USER") 指定所提供服务包含的角色或组。我们也不会在我们的例子中使用它,所以让我们让它暂时运行。 scopes ("read", "write")  是服务的范围 - 我们也不会在我们的应用程序中使用它。 autoApprove (true)-如果您必须自动批准客户的请求,我们会说是,以使应用程序更简单。 secret (passwordEncoder (). encode ("password")) 是客户端的密码。请注意,调用我们稍后定义的编码函数来指定密码将保存在何种类型的加密中。的编码功能进行注释与@Bean标签因为Spring,当我们在HTTP请求中提供密码时,会查找一个  PasswordEncoder对象检查交付密码的有效性。最后,我们有一个函数   configure (AuthorizationServerEndpointsConfigurer endpoints) ,我们定义哪个身份验证控制器和标识符存储应该使用端点。澄清终点是我们将与我们的“银行”联系以请求卡的URL。现在,我们已经创建了我们的身份验证服务器,但是根据引入的凭据,我们仍然需要他知道我们是谁并将我们放在不同的组中的方式。好吧,为此,我们将使用与保护网页相同的类。现在,我们可以检查我们的授权服务器是否有效。让我们看看如何使用优秀的PostMan程序。我们将使用HTTP请求类型POST,表明我们要使用基本验证。在我们的示例中,我们将分别使用“client”和“password”来设置用户和密码,即“银行”的密码。在请求正文和form-url编码格式中,我们将介绍要请求的服务,用户名和密码。'access_token'“ 8279b6f2-013d-464a-b7da-33fe37ca9afb ”是我们的信用卡,是我们必须提供给我们的资源服务器(商店)以查看非公开的页面(资源)的信用卡。创建资源服务器(ResourceServer)现在我们有了信用卡,我们将创建接受该卡的商店。在我们的示例中,我们将使用Spring Boot在相同的程序中创建资源和身份验证服务器,它无需配置任何内容。如果像现实生活中一样,资源服务器在一个地方,而身份验证服务器在另一个地方,我们应该向资源服务器指出哪个是我们的“银行”以及如何与之交谈。但是,我们将把它留给另一个条目。资源服务器的唯一类是  ResourceServerConfiguration:由于身份验证和资源服务器在同一个程序中,我们只需要配置资源服务器的安全性。这是在函数中完成的:一旦我们创建了资源服务器,我们必须只创建服务,这些服务是通过这些行完成的:现在让我们看看验证的工作原理。首先,我们检查我们是否可以在没有任何验证的情况下访问“/ publica”:如果我尝试访问“/ private”页面,则会收到错误“401 unauthorized”,表示我们无权查看该页面,因此我们将使用我们的授权服务器给用户授权。如果我们可以看到我们的私人页面,那么让我们尝试管理员的页面:我们当然没办法看到管理员的界面。因此,我们将要求凭据管理员提供新令牌,但要向用户“管理员”表明身份。返回的令牌是:“ab205ca7-bb54-4d84-a24d-cad4b7aeab57。” 这样就没问题了,我们可以安全地去购物!现在,我们只需要设置商店并拥有产品。本人创业团队产品MadPecker,主要做BUG管理、测试管理、应用分发,有需要的朋友欢迎试用、体验!本文为MadPecker团队产品经理译制,转载请标明出处

September 9, 2019 · 1 min · jiezi

ApiBoot - ApiBoot Security Oauth 依赖使用文档

ApiBoot是一款基于SpringBoot1.x,2.x的接口服务集成基础框架, 内部提供了框架的封装集成、使用扩展、自动化完成配置,让接口开发者可以选着性完成开箱即用, 不再为搭建接口框架而犯愁,从而极大的提高开发效率。引入 ApiBoot Security Oauth在pom.xml配置文件内添加如下:<!–ApiBoot Security Oauth–><dependency> <groupId>org.minbox.framework</groupId> <artifactId>api-boot-starter-security-oauth-jwt</artifactId></dependency>ApiBoot所提供的依赖都不需要添加版本号,但是需要添加版本依赖,具体查看ApiBoot版本依赖配置参数列表ApiBoot在整合SpringSecurity、Oauth2时把配置参数进行了分离,配置列表如下所示:整合SpringSecurity配置列表配置名称介绍默认值生效方式api.boot.security.awaySpringSecurity读取用户的方式,默认为内存方式memoryallapi.boot.security.auth-prefix拦截的接口路径前缀,如:/api/users就会被默认拦截/api/memory/jdbcapi.boot.security.users配置用户列表,具体使用查看内存方式介绍无memoryapi.boot.security.ignoring-urlsSpring Security所排除的路径,默认排除Swagger、Actuator相关路径前缀/v2/api-docs/swagger-ui.html/swagger-resources/configuration/security/META-INF/resources/webjars//swagger-resources/swagger-resources/configuration/ui/actuator/memory/jdbcapi.boot.security.enable-default-store-delegate仅在Jdbc方式生效truejdbc整合Oauth2配置列表配置名称介绍默认值绑定awayapi.boot.oauth.awayOauth存储Token、读取Client信息方式memoryallapi.boot.oauth.cleint-idOauth2 Client IDApiBootmemoryapi.boot.oauth.client-secretOauth2 Client SecretApiBootSecretmemoryapi.boot.oauth.grant-types客户端授权方式Srtring[]{“password”}memoryapi.boot.oauth.scopes客户端作用域String[]{“api”}memoryapi.boot.oauth.jwt.enable是否启用JWT格式化AccessTokenfalsememory/jdbcapi.boot.oauth.jwt.sign-key使用JWT格式化AccessToken时的签名ApiBootmemory/jdbcApiBoot在整合SpringSecurity、Oauth2时配置进行了分离,也就意味着我们可以让SpringSecurity读取内存用户、Oauth2将生成的AccessToken存放到数据库,当然反过来也是可以的,相互不影响!!!内存方式(默认方式)Spring SecurityApiBoot在整合Spring Security的内存方式时,仅仅需要配置api.boot.security.users用户列表参数即可,就是这么的简单,配置用户示例如下所示:api: boot: security: # Spring Security 内存方式用户列表示例 users: - username: hengboy password: 123456 - username: apiboot password: abc321api.boot.security.users是一个List<SecurityUser>类型的集合,所以这里可以配置多个用户。Oauth2如果全部使用默认值的情况话不需要做任何配置!!!Jdbc方式前提:项目需要添加数据源依赖。Spring Security默认用户表ApiBoot在整合Spring Security的Jdbc方式时,在使用ApiBoot提供的默认结构用户表时只需要修改api.boot.security.away: jdbc即可,ApiBoot提供的用户表结构如下所示:CREATE TABLE api_boot_user_info ( UI_ID int(11) NOT NULL AUTO_INCREMENT COMMENT ‘用户编号,主键自增’, UI_USER_NAME varchar(30) DEFAULT NULL COMMENT ‘用户名’, UI_NICK_NAME varchar(50) DEFAULT NULL COMMENT ‘用户昵称’, UI_PASSWORD varchar(255) DEFAULT NULL COMMENT ‘用户密码’, UI_EMAIL varchar(30) DEFAULT NULL COMMENT ‘用户邮箱地址’, UI_AGE int(11) DEFAULT NULL COMMENT ‘用户年龄’, UI_ADDRESS varchar(200) DEFAULT NULL COMMENT ‘用户地址’, UI_IS_LOCKED char(1) DEFAULT ‘N’ COMMENT ‘是否锁定’, UI_IS_ENABLED char(1) DEFAULT ‘Y’ COMMENT ‘是否启用’, UI_STATUS char(1) DEFAULT ‘O’ COMMENT ‘O:正常,D:已删除’, UI_CREATE_TIME timestamp NULL DEFAULT current_timestamp() COMMENT ‘用户创建时间’, PRIMARY KEY (UI_ID)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT=‘ApiBoot默认的用户信息表’;自定义用户表如果你的系统已经存在了自定义用户表结构,ApiBoot是支持的,而且很简单就可以完成整合,我们需要先修改api.boot.security.enable-default-store-delegate参数为false,如下所示:api: boot: security: # Spring Security jdbc方式用户列表示例 enable-default-store-delegate: false away: jdbc添加ApiBootStoreDelegate接口实现类,如下所示:@Componentpublic class DisableDefaultUserTableStoreDelegate implements ApiBootStoreDelegate { @Autowired private PasswordEncoder passwordEncoder; / * 用户列表示例 * 从该集合内读取用户信息 * 可以使用集合内的用户获取access_token / static List<String> users = new ArrayList() { { add(“api-boot”); add(“hengboy”); add(“yuqiyu”); } }; /* * 根据用户名查询用户信息 * * @param username 用户名 * @return * @throws UsernameNotFoundException / @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (!users.contains(username)) { throw new UsernameNotFoundException(“用户:” + username + “不存在”); } return new DisableDefaultUserDetails(username); } @Data @AllArgsConstructor @NoArgsConstructor class DisableDefaultUserDetails implements UserDetails { private String username; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return new ArrayList() { { add((GrantedAuthority) () -> “ROLE_USER”); } }; } /* * 示例密码使用123456 * * @return */ @Override public String getPassword() { return passwordEncoder.encode(“123456”); } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }}根据上面代码示例,我们可以通过users用户列表进行访问获取access_token。Oauth2创建Oauth所需表结构Oauth2如果使用Jdbc方式进行存储access_token、client_details时,需要在数据库内初始化Oauth2所需相关表结构,oauth-mysql.sql添加客户端数据初始化Oauth2表结构后,需要向oauth_client_details表内添加一个客户端信息,下面是对应ApiBoot Security Oauth配置信息的数据初始化,如下所示:INSERT INTO oauth_client_details VALUES (‘ApiBoot’,‘api’,’$2a$10$M5t8t1fHatAj949RCHHB/.j1mrNAbxIz.mOYJQbMCcSPwnBMJLmMK’,‘api’,‘password’,NULL,NULL,7200,7200,NULL,NULL);AppSecret加密方式统一使用BCryptPasswordEncoder,数据初始化时需要注意。在上面memory/jdbc两种方式已经配置完成,接下来我们就可以获取access_token。获取AccessToken通过CURL获取➜ ~ curl ApiBoot:ApiBootSecret@localhost:8080/oauth/token -d “grant_type=password&username=api-boot&password=123456”{“access_token”:“eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTMxMDk1MjMsInVzZXJfbmFtZSI6ImFwaS1ib290IiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjBmZTUyY2RlLTBhZjctNDI1YS04Njc2LTFkYTUyZTA0YzUxYiIsImNsaWVudF9pZCI6IkFwaUJvb3QiLCJzY29wZSI6WyJhcGkiXX0.ImqGZssbDEOmpf2lQZjLQsch4ukE0C4SCYJsutfwfx0”,“token_type”:“bearer”,“expires_in”:42821,“scope”:“api”,“jti”:“0fe52cde-0af7-425a-8676-1da52e04c51b”}启用JWTApiBoot Security Oauth在使用JWT格式化access_token时非常简单的,配置如下所示:api: boot: oauth: jwt: # 开启Jwt转换AccessToken enable: true # 转换Jwt时所需加密key,默认为ApiBoot sign-key: 恒宇少年 - 于起宇默认不启用JWT,sign-key签名建议进行更换。本章源码地址:https://github.com/hengboy/api-boot/tree/master/api-boot-samples/api-boot-sample-security-oauth-jwt ...

April 4, 2019 · 2 min · jiezi

Authlib强大OAuth框架入门

基于Python的Authlib是集所有主流WebAPI权限认证协议的客户端、服务端、底层实现、高层架构于一身的强大工具库。参考官方:Authlib: Python AuthenticationAuthlib几乎是能将RFC所有相关的API认证协议都包括进来了,甚至从协议的底层实现、高层架构,从客户端到服务端都能实现的,当之无愧称为Monolithic project 的一个项目。目前Authlib支持的Authentication协议有:OAuth 1.0OAuth 2.0JWTmany more…安装:$ pip install AuthlibOauth2.0客户端验证参考官方:Authlib - Client Guide - OAuth 2 SessionAuthlib中用来登录验证OAuth2.0的对象叫Session,其中包括了所有相关的验证所需方法函数。from authlib.client import OAuth2Session# 生成session,用来之后的创建URL、获取token、刷新token等所有动作session = OAuth2Session( client_id=‘Your Client ID’, client_secret=‘Your Client Secret’, scope=‘user:email’, # 这个授权范围根据每个API有所不同 redirect_uri=‘https://MyWebsite.com/callback')# 生成URLuri, state = session.create_authorization_url( ‘https://目标网址的授权入口/authorize’)print(uri)# 「手动」打开浏览器访问URI,登录API帐户,点击授权,然后获取最终的URL# 或者自己有服务器的话,可以自己接收#。。。# 将callback返回的URL复制下来,因为其中包含授权codeauthorization_response = ‘https://MyWebsite.com/callback?code=42..e9&state=d..t'# 用获得的Code去访问access_token入口tokens = session.fetch_access_token( access_token_url=‘https://目标网址的授权入口/api/access_token’, authorization_response=authorization_response)print(tokens) #返回字典格式: {‘access_token’: ’e..ad’, ’token_type’: ‘bearer’, ‘scope’: ‘user:email’}# 过期后,刷新token。需重建session对象:session = OAuth2Session( client_id=‘Your Client ID’, client_secret=‘Your Client Secret’, scope=‘user:email’, state=state, redirect_uri=‘https://MyWebsite.com/callback')new_tokens = session.refresh_token( access_token_url, refresh_token=tokens[‘refresh_token’])print(’[Refreshed tokens]:’, new_tokens)设置的callback或redirect_url不存在怎么获取Code?在调试过程中,如果我们向上面一样手动去打开浏览器复制URL,再复制回应过来的URL是很麻烦的。Oauth2的逻辑就是:要求各种客户自己在自己的浏览器里登录帐户,然后给你的App授权。所以这一步redirect_url是躲不过的。但是我们测试过程中,还没来得及专门建一个服务器或网页来接收这个callback回调怎么办呢?有办法!方法一:直接截取我们可以在第一次登录并授权后,复制cookies,然后在测试中直接使用requests带着cookies登录信息去访问,就不再需要手动打开浏览器了:raw_cookies = """ 这里是你复制过来的cookies “““cookies = dict([line.split("=”, 1) for line in raw_cookies.strip().split(”; “)])try: r = requests.get(uri, cookies=cookies, allow_redirects=True)except requests.exceptions.ConnectionError as e: print( ‘[Final URL]: ‘, e.request.url ) authorization_response = e.request.url由于你最开始设置的callback是公网上的某个网址,应该是不存在的(只要你没有设置的话)。所以,这里去request的时候,肯定会报错,且是ConnectionError。所以我们可以将最终报错的URL获取到,这个里面就包含了我们想要的Code码。方法二:更改本地hosts如果本地已经搭建了测试服务器,比如Nginx或Flask,这种方法更简单。比如在供应商中设定的redirect_url为http://example.com/callback,那么只需简单编辑hosts:# /etc/hosts127.0.0.1 example.com那么,只要本机设置了Nginx或Flask等服务器,只需要获取127.0.0.1/callback即可得到需要的内容。 ...

January 25, 2019 · 1 min · jiezi