本篇文章让我带你认识一下什么是oauth协议什么是oauth协议? 百度百科上解释:允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。 简单的来讲就是一个令牌,这个令牌可以有一定的权限,在不知道用户密码的情况下也可以进行部分的功功能操作。用一个例子帮助理解:一个甲方公司,公司里面使用一卡通,这张卡可以门禁,食堂,等等,公司招了外包进来,外包只能开通门禁就行,其他的权限是没有的。这时候公司就不会给一张正式员工的卡,而是外包的卡,正编员工卡就是用户的账号密码,这个外包卡就相当于是一个令牌,并且可能公司会给你的外包卡设置一个有效期,等有效期快到的时候有需要申请延期。这个就相当于是oauth协议模式。用户不会给你用户名和密码,那样相当于放开了所有的权限,而会给你提供一个令牌,在有效期类可以访问特定的功能服务使用令牌的优点:令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。令牌可以被数据所有者撤销,会立即失效。令牌有权限范围(scope),对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限oauth协议有四种模式; 1、授权码模式2、隐藏式3、密码式4、客户端凭证其中授权码方式是最常用的流程,安全性也最高,今天我们就来着重讲一下授权码模式。授权码模式:指的是第三方应用先申请一个授权码,然后再用该码获取令牌,授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。授权码模式主要分为几个步骤 以甲方公司员工卡系统(SelfResearch。com)和外包公司员工卡系统(outsource。com)为例,下面是授权码模式的流程 请求授权码 首先,甲方公司给外包员工方提供一个授权链接,外包员工点击连接,申请授权码,连接参数如下所示 https:SelfResearch。comoauthauthorize?responsetypecodeclientidCLIENTIDredirecturiCALLBACKURLscoperead responsetype参数表示要求返回授权码(code),clientid参数让甲方知道是谁在请求,redirecturi参数是甲方系统接受或拒绝请求后的跳转网址,scope参数表示要求的授权范围(这里是只读)。 返回授权码 用户跳转到这个之后,甲方公司会先要求用户登录,然后请求授权,如果同意就跳转到redirecturi这个参数的地址,并返回授权码 https:SelfResearch。comcallback?codeAUTHORIZATIONCODE code就是表示授权码 请求令牌 外包员工拿着授权码去请求令牌 https:SelfResearch。comoauthtoken?clientidCLIENTIDclientsecretCLIENTSECRETgranttypeauthorizationcodecodeAUTHORIZATIONCODEredirecturiCALLBACKURLclientid参数和clientsecret参数用来让甲方公司确认外包员工的身份(clientsecret参数是保密的,因此只能在后端发请求)。granttype参数的值是AUTHORIZATIONCODE,表示采用的授权方式是授权码。code参数是上一步拿到的授权码。redirecturi参数是令牌颁发后的回调网址。 返回令牌外包员工访问redirecturi会得到一串json数据:{accesstoken:67c4051b36c811ecaf3300163e0808bf,tokentype:bearer,refreshtoken:71975ccc36c811ecaf33cfd2826915e5,expiresin:3249,scope:read} accesstoken就是令牌了,用户需要访问其他接口就需要带上这个token去访问了refreshtoken这个是刷新令牌,如果需要使用新的token,就需要通过这个刷新令牌来获取最新的accesstoken。实现oauth2,可以分为三个步骤认证服务资源服务第三方服务 现在第三方用户(test9527)想去访问资源中的部分功能(接口),但是改功能只有User角色才能访问,需要先通过认证服务器获取user的授权码,然后拿着这个code和自己账号信息去获取token,并校验通过之后才能访问到资源服务器,也就是第三方用户通过test9527可以访问本来需要user权限才能访问的资源功能(接口) 实现步骤: 创建三个服务oauthserver(认证服务)、resourceserver(资源服务)、thirdserver(第三方服务 maven依赖!oauth2dependencygroupIdorg。springframework。security。oauthgroupIdspringsecurityoauth2artifactIdversion2。1。3。RELEASEversiondependency!springsecuritydependencygroupIdorg。springframework。bootgroupIdspringbootstartersecurityartifactIddependency oauthserver服务配置文件模拟第三方授权配置EnableAuthorizationServerConfigurationpublicclassAuthConfigextendsAuthorizationServerConfigurerAdapter{ResourceClientDetailsServiceclientDetailsS资源服务器校验TokenOverridepublicvoidconfigure(AuthorizationServerSecurityConfigurersecurity){security。checkTokenAccess(permitAll())。allowFormAuthenticationForClients();}第三方客户端请求配置,和资源服务访问的配置,不设置默认都可以访问,提供默认回调地址Overridepublicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{clients。inMemory()第三方用户。withClient(test9527)。secret(newBCryptPasswordEncoder()。encode(test9527))。resourceIds(resource)认证模式。authorizedGrantTypes(authorizationcode,refreshtoken)。scopes(all)回调地址。redirectUris(http:localhost:8082notify。html);}配置访问端点Overridepublicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints){endpoints。authorizationCodeServices(authorizationCodeServices())。tokenServices(tokenServices());}内存管理BeanAuthorizationCodeServicesauthorizationCodeServices(){returnnewInMemoryAuthorizationCodeServices();}Token管理规则BeanAuthorizationServerTokenServicestokenServices(){DefaultTokenServicesservicesnewDefaultTokenServices();services。setClientDetailsService(clientDetailsService);services。setSupportRefreshToken(true);services。setTokenStore(tokenStore());services。setAccessTokenValiditySeconds(3600);services。setRefreshTokenValiditySeconds(36007);}BeanTokenStoretokenStore(){returnnewInMemoryTokenStore();} 配置springsecurity模拟本地用户配置ConfigurationpublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{密码加密方式BeanpublicPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}内存中虚拟用户和角色Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth。inMemoryAuthentication()。withUser(user)。password(newBCryptPasswordEncoder()。encode(123456))。roles(user);}表单登录Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http。csrf()。disable()。formLogin();}} resourceserver配置资源服务管理配置ConfigurationEnableResourceServerpublicclassResourceServerConfigextendsResourceServerConfigurerAdapter{Token令牌校验BeanRemoteTokenServicestokenServices(){RemoteTokenServicesservicesnewRemoteTokenServices();services。setCheckTokenEndpointUrl(http:localhost:8080oauthchecktoken);services。setClientId(test9527);services。setClientSecret(test9527);}服务资源ID配置Overridepublicvoidconfigure(ResourceServerSecurityConfigurerresources)throwsException{resources。resourceId(resource)。tokenServices(tokenServices());}模拟用户权限规则Overridepublicvoidconfigure(HttpSecurityhttp)throwsException{http。authorizeRequests()访问user下的路径需要user角色。antMatchers(user)。hasRole(user)。anyRequest()。authenticated();} resource下的功能(接口) 第三方服务首先认证,获取授权码codehttp:localhost:8080oauthauthorize?clientidtest9527responsetypecodescopeallredirecturihttp:localhost:8082notify。html 此时会到认证服务器中的user认证 此时需要user用户同意授权,当认证服务中的user用户同意之后,到如下页面,此时看接口可以知道已经拿到code授权码,并跳转到我们需要跳转的地址 redirecturihttp:localhost:8082notify。html 拿到授权码之后访问回调地址http:localhost:8082notify。html?codeRs067L然后通过code,clientid,clientsecret等参数访问获取令牌地址https:SelfResearch。comoauthtoken?clientidCLIENTIDclientsecretCLIENTSECRETgranttypeauthorizationcodecodeSMD5njredirecturiredirecturihttp:localhost:8082notify。html成功之后会返回token,刷新token,以及token有效时间,如下 拿到token之后,我们再去访问资源服务器,此时就能顺利访问到功能(接口)了 最终效果,最终第三方用户test9527访问当了资源服务器功 至此认证授权完毕,如有错误欢迎指出,共同学习进步 代码地址getee:https:gitee。comcoolhy123oauth。git 参考:https:segmentfault。coma1190000038574022