SpringBoot使用security实现OAuth2
OAuth2
OAuth
是一个开放标准,允许用户授权地方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或者分享他们数据的所有内容。
我们从一个常见的例子来看:
我们打王者,第一次登录的时候要求我们选择微信登录还是QQ
登录,这时假设我们点击QQ
登录,那么就会跳转到一个认证界面,询问我们是否同意王者使用QQ
的数据,例如好友列表等等。当我们点击同意之后就会跳转回王者,之后进入王者我们可以发现好友列表内容就是我们的QQ
中的好友列表。并且过段时间不登录之后,我们会发现又要再次认证,这是因为之前的认证令牌过期了,需要重新申请。
这就是OAuth
的一个大概思路流程
- 客户端要求用户给予授权
- 用户同意授权
- 客户端通过获得授权向认证服务器申请
token
- 认证服务器对客户端进行认证,通过认证之后发放
token
- 客户端可以通过
token
向资源服务器申请资源 - 资源服务器确认通过之后,向客户端开放资源
OAuth2
又分为四种不同的授权模式(简化模式和密码模式由于安全度太低已被遗弃):
- 授权码模式:这是最常用也是安全度最高的一种模式,通过获取授权码增加安全性
简化模式:直接申请令牌并且返回令牌,主要用于申请端只有前端没有服务器的情况,例如微信小程序密码模式:需要用户提供账号密码,通过账号密码获取token
,这种模式安全度极低,不推荐- 客户端模式:与用户无关的一种模式,直接是服务器之间的通信,例如内部系统间的
API
调用
接下来主要讲讲授权码这个核心授权模式
授权码模式
授权码模式authorization code
,指的是客户端首先向认证服务器申请一个授权码,然后通过该授权码再去向授权服务器申请token
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(B)-- User authenticates --->| Server |
| | | |
| -+----(C)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(A) (C) | |
| | | |
^ v | |
+---------+ | |
| |>---(D)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(E)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)
步骤如下:
A 用户访问客户端,客户端将用户导向认证服务器,并且携带重定向URI
https://authorization-server.com/auth?
response_type=code
&client_id=CLIENT_ID
&redirect_uri=REDIRECT_URI
&scope=photos
&state=1234zyx
&code_challenge=CODE_CHALLENGE
&code_challenge_method=S256
response_type=code
表示授权类型为授权码模式
client_id
表示客户端ID
,第一次创建应用的时候获得
redirect_uri
表示重定向URI
用户在认证完成之后将用户返回到特定URI
scope
表示申请的权限范围,例如READ
state
应用随机指定的值,用于后期验证
code_challenge
code_challenge=transform(code_verifier,[Plain|S256])
如果method=Plain
,那么code-challenge=code_verifier
如果method=S256
,那么code_challenge
等于code_verifier
的Sha256
哈希
在授权码请求中带上code_challenge
以及method
,这两者与服务器颁发的授权码绑定。
code_verifier
为客户端生成一个的随机字符串
客户端在用授权码换取token
时,带上初始生成的code verifier
,根据绑定的方法进行计算,计算结果与code_challenge
相比,如果一致再颁发token
code_challenge_method=S256
标明使用S256 Hashing
方法
B 用户选择是否对客户端授权
C 授权之后,认证服务器将用户导向之前传入的重定向URI
,并且附上授权码
如果用户点击了Allow
了,那么服务器将重定向并且附上授权码
https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx
code
即为授权码,授权码有效期很短,一般为10分钟,并且客户端只能使用一次。该码与客户端ID
和重定向URI
是一对一关系
state
之前传入的state
我们首先要比较传入的state
与之前的state
是否相同(之前的state
可以存在cookie
中),用于确认没有被劫持。<