Spring Security Oauth2.0授权模式
概要:
springboot security提供了4种授权模式,分别为密码模式、授权码模式、客户端凭证模式和隐式模式;前三种是实际开发中会用到的授权模式,第4种在后续高版本模式中已经被废弃了。基于spring security提供的扩展接口我们也可以自定义自己的授权方式,比如微信登录、短信登录、手机号一键登录等。接下来简单记录下前三种授权模式概念,后续会跟踪源码流程。
这三种模式虽然有差异,但大体上都可以分为三个阶段:请求客户端验证、授权信息验证、生成token返回。可以看到不管哪种模式都需要客户端认证,即不是随便一个客户端都可以访问security保护的资源,需要特定的客户端才可以访问。oauth2.0为我们提供了客户端认证相关的表sys_oauth_client,需要提前把认可的客户端信息内置到表中,访问的客户端需要携带这些认证信息。如下截图内置了一个client_id为cicada客户端。
客户端认证信息携带
客户端认证信息携带需要符合security规范定义,才可以被security顺利解析出来。有两种方式可以携带客户端信息。
方式一:
可以直接在header里面写死客户端client的信息,格式为Basic xxxxx,其中后面的xxxx为数据库中内置的客户端信息client_id:client_secret拼接后使用base64encode得到的字符串。比如上面内置的cicada客户端,最终存入header中的信息为:key:Authorization, value:Basic Y2ljYWRhOmNpY2FkYQ==
方式二:
使用模拟工具的Authorization认证,类型选择为Basic Auth(必须为该类型,源码中规定死的),填写客户端信息,在请求接口时会在header中生成上面的key/value信息。推荐使用第二种方式。
密码模式
密码模式就是请求客户端需要提供账号密码,同时header中携带认可的客户端信息,服务器端验证信息后返回at或者刷新rt。
密码模式获取token请求参数:
密码模式返回的access_token信息
这里的用户信息也是需要内置数据库中的,oauth2.0提供了sys_user表。
token都是有时效性的,token的刷新需要以如下的参数请求刷新,grant_type为refresh_token,at的值为上面生成的access_token。
授权码模式
授权码模式比较复杂,大体业务路程解释:用户user需要访问受保护的资源服务A,但是又不想注册服务A的账密,这时可以使用服务A提供的授权登录方式,如微信、支付宝登录,用户被引导至登录对应登录方式的登录业务,扫码确认登录后三方授权服务器B(如微信后端、支付后台)返回一个授权码给到服务器A的前端页面,前端页面再把授权码给到服务A的后端,后端拿到该授权码后去请求对应的授权服务器B获取AT(access_token),再使用AT去获取当前用户的信息,如用户id,头像、手机号等,同时返回给前端页面,完成登录过程,然后用户user就可以正常访问受保护的服务A的资源了。
用户选择授权方式,这里选择是账号密码登录,也可以是接入三方扫描登录,如微信、支付宝登录。
登录后在弹出授权确认页面,有些三方授权方式,还可以勾选授权范围,比如仅授权账号、头像信息,不授权手机号。
统一授权后,页面会重定向到security中配置的回调地址页面,同时携带一个code,如下;
这里客户端重定向地址配置的是百度
最后使用上面返回的code去三方(我这里的三方服务还是后端自己模拟的)换取token
客户端凭证模式
请求方携带服务方分配的客户端id和客户端密钥,向授权服务请求令牌。该模式适用于公司自己的后端服务与后端服务之间交互。与授权码模式相比,客户端凭证模式没有请求者手动授权确认过程,也没有code换取令牌的过程,只要客户端id和密钥验证通过即返回at和rt。客户端凭证模式比较简单不再提供截图。