云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

香港服务器_维普论文数据库_年度促销

小七 141 0

通过工作线程的OAuth身份验证服务器

假设我拥有一个服务,我想代表我的用户授予其他服务访问我的服务的权限。熟悉的oauth2.0是Google登录、Facebook等使用的行业标准,可以在不给用户带来不便的情况下安全地进行通信。实现OAuth身份验证服务器在概念上很简单,但在实践中却很痛苦。我们可以利用Cloudflare Workers的功能来简化实现、减少延迟,并将服务逻辑与身份验证层隔离开来。对于那些不熟悉OAuth的人,我强烈建议您阅读一篇更深入的文章。OAuth 2.0工作流的步骤如下:使用者服务将用户重定向到由身份验证服务器设置的回调URL。在这个回调URL中,auth服务器要求用户登录并接受消费者权限请求。身份验证服务器使用代码将用户重定向到使用者服务。使用者服务请求将此代码交换为访问令牌。消费者服务通过在回调URL中包含客户机机密来验证其身份。身份验证服务器向使用者提供访问令牌。使用者服务现在可以使用访问令牌代表用户获取资源。在本文的其余部分中,我将使用一个Worker遍历OAuth身份验证服务器的实现。为了简单起见,我假设用户已经登录并获得了JWT形式的会话令牌,在这里我将其称为"令牌"。我的完整实现有一个更彻底的流程,包括初始用户登录和注册。安装程序我们必须能够引用有效的用户会话、代码和登录信息。因为worker在执行之间不维护状态,所以我们将使用Cloudflare存储来存储这些信息。我们设置了三个名称空间:用户、代码和令牌。在OAuth服务器域上,创建两个名为auth和token的空工作线程脚本。将三个名称空间绑定到两个worker脚本。然后将名称空间配置为脚本,使您的资源最终看起来像:要使用KV存储语法从存储中放置和获取项目://@ts忽略代码.get("user@ex.com用户")我们包括//@ts忽略前面所有的KV存储命令。我们在本地没有这些变量的类型定义,否则Typescript将在编译时抛出错误。要使用Typescript和Cloudflare预览器设置项目,请关注以下博客文章。Webpack允许我们导入需要使用JWT库jsonwebtoken。从"jsonwebtoken"导入*为jwt;记住跑步:npm install jsonwebtoken和npm install@types/jsonwebtoken或者,我们可以设置一个文件来指定端点和凭证。从"./private"导入{hosts};export const credentials={/*为了演示目的,最好使用KV来存储机密*/客户:[{id:"维多利亚客户端",秘密:"维多利亚教堂"}],储存:{秘密:"从KV解密的秘密"}};导出常量路径={授权:{授权:主机.auth+"/授权",登录:主机.auth+"/登录",代码:主机.auth+"/code",},令牌:{资源:hosts.token+"/资源",令牌:hosts.token+"/授权",}}1回调后接受页面消费者服务生成一些回调URL,将用户重定向到我们的认证服务器。然后,身份验证服务器向用户显示登录或接受页面,以生成代码。因此,身份验证服务器必须监听authorizeurl端点并返回giveLoginPageResponse。addEventListener("获取",(事件:获取事件)=>{const url=新url(event.request.url);如果(url.pathname.includes("/授权")返回事件响应(给出响应(事件请求));}导出异步函数giveLoginPageResponse(请求:请求){…检查我不需要登录的情况。。。let token=getTokenFromRequest(请求)if(token){//用户已登录返回新响应(giveAcceptPage(请求)}因为用户已经有一个存储的会话,所以我们可以使用一个方法giveAcceptPage。显示accept页并返回重定向以生成代码。导出函数giveAcceptPage(请求:请求){let req_url=新url(请求.url);让params=req_网址.search让fetchCodeURL=路径验证码+参数返回"在在接受在在`;}2重定向回"消费者"在fetchCodeURL的端点,身份验证服务器将用户的浏览器重定向到用户的页面,如代码回调的原始URL参数中的redirect_uri所指定的那样。addEventListener("获取",(事件:获取事件)=>{...如果(url.pathname.includes("/code")返回事件响应(重定向代码到消费者(事件请求));}导出异步函数redirectCodeToConsumer(请求:请求){让会话=等待验证用户(请求)如果(会话.msg=="403")返回新响应(give403Page(),{status:403})如果(会话.msg=="dne")返回寄存器newuser(会话.电子邮件, 会话.pwd)让代码=数学随机().toString(36).子串(2,12)试试看{let req_url=新url(请求.url)让redirect_uri=新URL(encodeURI(req_url.searchParams.get("重定向"uri"))让client_id=新的URL(encodeURI(req_url.searchParams.get("客户机号"))//@ts忽略等待代码.put(客户账号+邮箱,代码)重定向_uri.searchParams.set("代码",代码);重定向_uri.searchParams.set("响应类型","代码");返回响应.重定向(重定向_uri.href,302);}接球(e){//@ts忽略等待代码.删除(电子邮件,代码)返回新响应(JSON.stringify(factoryerror({message:"传入"+e}的URL出错"),{状态:500});}}三。代码到令牌交换现在消费者有了密码。他们可以使用此代码请求令牌。在我们的令牌工作者上,配置端点以交换消费者服务的代码以授予令牌。addEventListener("获取",(事件:获取事件)=>{...如果(url.pathname.includes("/token"))返回事件响应(赠券(事件请求));从请求中获取代码,并验证此代码是否与为此客户机存储的代码匹配。验证代码后,通过从KV存储器中获取现有令牌或签署用户信息以生成新令牌来交付令牌。导出异步函数giveToken(请求:请求){let req_url=新url(请求.url);let代码=req_url.searchParams.get("代码");让电子邮件=请求_url.searchParams.get("电子邮件");如果(代码){如果(!validClientSecret(请求)返回errorResponse()//@ts忽略let storedCode=等待代码.get(电子邮件)如果(代码!=storedCode)返回新响应(give403Page(),{状态:403})让tokenJWT=jwt.标志(电子邮件,凭据.client.secret);... 返回令牌4将代币交给消费者继续执行giveToken方法的第3步,使用此有效令牌响应使用者。...标题.append("set cookie","token=Bearer"+tokenJWT);//@ts忽略等待代币(电子邮件、令牌jwt)var respBody=工厂令牌响应({"访问令牌":令牌jwt,"token_type":"承载","到期日":2592000,"refresh_token":代币,"令牌":令牌})}其他{respBody.errors.push(factoryerror({message:"没有代码发送到授权令牌url"}))}返回新响应(JSON.stringify(respBody),{headers};}5接受令牌现在,作为OAuth 2.0身份验证服务器,您的职责已经完成!希望使用您的服务的消费者服务具有您没有如此神奇地生成的令牌。使用者服务器将发送一个包括令牌的请求:获得/资源/一些货物授权:持有人eyJhbGci..bGAqA身份验证服务器将验证令牌并给出货物:导出异步函数giveResource(请求:请求){var respBody:HookResponse=factoryHookResponse({})让令牌=""让decodedJWT=factoryJWTPayload()try{//validate request是他们声明的对象令牌=获取cookie(请求.headers.get("cookie"),"令牌")如果(!令牌)令牌=请求.headers.get("授权")。子字符串(7)解码djwt=jwt.验证(代币,凭证.storage.secret)//@ts忽略let storedToken=等待代币(解码Djwt.sub)if(isExpired(storedToken))throw new Error("token is expired")/*TODO而不是抛出Error send to refresh*/如果(储存好了!=token)抛出新错误("token与存储的内容不匹配")}接球(e){respBody.errors.push(factoryerror({message:e.message,类型:"oauth"}))返回新响应(JSON.stringify(respBody),初始化)}响应体=GetUsersPersonBody(解码Djwt.sub)返回新响应(JSON.stringify(respBody),初始化)}serverless的边界每天都在不断扩展,但是如果你的应用程序只需要授权用户,那么使用Cloudflare访问可能会更好。我们已经演示了使用Cloudflare worker和存储可以实现全面的oauth2.0身份验证服务器实现。请继续关注OAuth消费者实现的后续博客文章。