成熟是一种明亮而不刺眼的光辉,一种圆润而不腻耳的音响。
1 前言
OAuth2.0(开发授权) 是一个开发的标准,主要是解决第三方应用访问存在在该服务的用户信息,而不需要将用户账户密码同步给第三方,解决了用户登录的问题,在公众号、小程序、H5等应用服务越来越多的情况下,能够很好的解决用户的体验问题。基于此有必要总结一下相关的内容。OAuth2.0 只是解决了一个授权的问题,但是用户还是需要一次的登录,而这个权限需要依赖安全管理框架,而 OAuth2.0 一般是和 SpringSecurity 一起使用。在本文中还将引入 gateway 网关,只介绍授权码的方式,通过应用回调来处理授权问题。
2 项目结构
在项目中主要有四个部分:
- 1 网关服务,负责请求的鉴权和请求分发。
- 2 授权服务,负责用户的授权和用户登录。
- 3 商品服务和订单服务,具体的业务系统。
3 授权码模式
3.1 授权流程
OAuth2.0 授权码模式是应用十分广泛的模式,具体流程如下时序图所示:
再使用 OAuth2.0 之前,需要先引入相关的依赖,这里采用的是 springboot 2.7.0
, springcloud 2021.0.3
, springcloud-alibaba 2021.0.1.0
,oauth 2.2.5.RELEASE
, security 2.7.0
这里采用的都是比较最新的版本,核心的依赖如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
3.2 授权配置信息
关于 OAuth2.0 的相关配置,主要是 AuthorizationServerConfigurerAdapter
相关的内容,其中有一下几个重要的配置内容:
- 1 AuthorizationServerSecurityConfigurer 权限的配置信息,这里的配置信息包括表单提交权限验证信息,可以对
/oauth/check_token
和/oauth/token_key
进行授权,前者用来资源服务器校验token 信息, 后者在使用jwt令牌时提供公有密钥端点。在这里需要再介绍一下,/oauth/authorize
是AuthenticationEndpoint
用来处理认证请求的。/oauth/token
是TokenEndpoint
是处理访问令牌请求的。
- 2 AuthorizationServerEndpointsConfigurer 令牌和端点的配置信息, 这里需要的配置有
authenticationManager
,是springsecurity
的鉴权管理器,refresh_token 是否重用,以及用户的登录查询UserDetailsService
,accessTokenConverter
用来生成 token 信息,以及allowedTokenEndpointRequestMethods
用来配置接口访问的方法。tokenEnhancer
则是 token 的增强信息配置。endpoints.pathMapping
则是自定义接口的,对接口进行重写。
- 3 ClientDetailsServiceConfigurer 客户端信息的初始化配置,这里有两种方式存储,可以使用数据库配置也可以使用内存的方式进行处理。其中关键的配置有
client_id
用来标识客户id,secret
是客户端的安全码配置,scope
是用来限制客户端的访问范围,如果是空或者all 则可以访问全部范围。authorizedGrantTyoes
标识客户端的授权类型,此处使用的是授权码模式,为authorization_code
。authorities
为该客户端的使用权限范围。autoApprove
是标识自动授权,默认为 false, 最后还有一个回调地址redirectUris
。这里采用的是数据库配置,在数据库中的配置如下所示:
在下图中,也可以看到 inMemory
的配置信息
3.3 token 信息增强
默认情况下 jwt 返回的内容不足以获取全部的信息,一般情况下需要对 token 的信息进行增强,以边传输信息。
进行增强配置后,获取到的 OAuth2AccessToken
到的结构信息如下图所示:
默认的返回信如下图: 增强后的 token 结构信息如下所示:
3.4 重写 oauth 2.0的授权页面
在 3.2 中,我们已经知道了通过 endpoints.pathMapping
来处理授权页面的重写,那么在web 层就可以自定义授权页面的控制器,不过在这里要注意,加上这个 SessionAttributes
注解,这里的视图层采用的是 freemaker 进行渲染,传入前端的参数有 clientId 和授权范围 scope。
重写后的页面如下图所示:
3.5 重写登录认证接口
默认情况下,/oauth/token
可以使用 OAuth 的接口,但是可以根据需要重写认证接口,这里注入的是 TokenEndpoint
,使用 tokenEndpoint.postAccessToken
方法进行处理,获取 OAuth2AccessToken
信息。
4 授权模式回调
在授权码模式下,授权服务器会生成一个code 码,回调资源服务器的回调地址,资源服务器根据code码和client 的配置信息去授权服务器获取 token 信息。 在这里介绍一下几个比较重要的接口。
# 获取以及刷新 token 信息, 获取授权信息以及检查token 信息
/oauth/token
/oauth/authorize
/oauth/check_token
回调是资源服务器向授权服务器进行获取 token 的接口,一个授权码只能使用一次,这样最大限度的保证了用户数据的安全性以及数据获取的便利性。
5 SpringSecurity 相关配置
针对 SpringSecurity
的配置大家都不陌生,主要是继承 WebSecurityConfigurerAdapter
重写 configure
方法即可。
这里需要强调一下,需要声明用户的登录地址,否则当用户访问授权时,需要登录跳转时,会报404 的错误或者登录地址配置失效。
关于 security 的其它配置,不是本文的重点,这里就不展开讲述了。重写后的登录页面如下图所示:
6 网关配置
关于网关 gateway 的配置信息,需要先引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
这里采用的是响应式编程,使用 webflux
而不是 webmvc
, gateway 的配置包含基本的路由配置规则以及权限验证。
下图是 gateway 相关的配置信息,主要是配置相关的过滤器以及鉴权处理。
ReactiveAuthorizationManager
主要用来判断用户是否有资源访问权限,ServerAuthenticationEntryPoint
用来处理成功的返回结果,ServerAccessDeniedHandler
用来处理无权限的情况。
下图是 ReactiveAuthorizationManager
的配置信息,主要是控制用户对资源的访问权限,只有用户有访问资源的权限才可以访问资源内容。
此外还可以对 ServerHttpSecurity.addFilterBefore
进行配置,添加过滤器,控制过滤器的访问顺序,这里实现的都是 WebFilter
, 此外还可以配置全局过滤器 GlobalFilter
。
7 接口访问
在完成了授权服务和网关配置后,还有两个微服务的项目需要创建,这里比较简单就不展开讲述了,在文末的项目源码中可以获取。
项目使用了 nacos 作为配置中心和注册中心,如下图所示:
访问接口如下图所示:
刷新 token 如下图所示:
8 总结
在本文中,主要介绍了 Oauth2.0
和 springsecurity
进行鉴权和开放授权,使用了 springcloud-gateway
作为网关, nacos
作为注册中心和配置中心,采用 redis 进行接口权限的配置,使用 mysql
存储 oauth2.0
的配置信息以及用户信息,在后续的文章中将继续分享网关相关的内容。
项目代码已经上传到 github 上。 springboot-auth
【项目参考及推荐】
本文正在参加 「金石计划 . 瓜分6万现金大奖」