一、授权模式
1.1授权码模式
下图为授权码模式交互图:
① 资源拥有者打开客户端,客户端要求资源拥有者给予授权,它将浏览器被重定向到授权服务器,重定向时会附加客户端的身份信息。如:http://localhost:3001/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
;
参数列表如下:
- client_id:客户端准入标识
- response_type:授权码模式固定为
code
- scope:客户端权限
- redirect_uri:跳转
uri
,当授权码申请成功后会跳转到此地址,并在后边带上code
参数(授权码)
②浏览器出现向授权服务器授权页面,之后将用户同意授权。
③授权服务器将授权码(AuthorizationCode
)转经浏览器发送给client
(通过redirect_uri
)
④客户端拿着授权码向授权服务器索要访问access_token
,请求如下:http://localhost:3001/oauth/token? client_id=c1&client_secret=secret&grant_type=authorization_code&code=5PgfcD&redirect_uri=http://w ww.baidu.com
⑤授权服务器返回令牌(access_token
)
这种模式是四种模式中最安全的一种模式。一般用于client
是Web
服务器端应用或第三方的原生App
调用资源服务的时候。因为在这种模式中access_token
不会经过浏览器或移动端的App
,而是直接从服务端去交换,这样就最大限度的减小了令牌泄漏的风险。
测试:
浏览器访问认证页面:
http://localhost:3001/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
然后输入模拟的账号和密码点登陆之后进入授权页面
确认授权后,浏览器会重定向到指定路径并附带授权码,最后使用该授权码获取token。
获取token
成功:
1.2简化模式
下图是简化模式交互图:
①资源拥有者打开客户端,客户端要求资源拥有者给予授权,它将浏览器被重定向到授权服务器,重定向时会 附加客户端的身份信息。如:http://localhost:3001/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
参数描述同授权码模式 ,注意response_type=token
。
②浏览器出现向授权服务器授权页面,之后将用户同意授权。
③授权服务器将授权码将令牌(access_token
)以Hash
的形式存放在重定向uri
的fragment
中发送给浏览器:
注:fragment
主要是用来标识URI
所标识资源里的某个资源,在URI
的末尾通过(#)作为 fragment
的开头,js
通过响应浏览器地址栏变化的方式能获取到fragment
就行了。
简化模式用于没有服务器端的第三方单页面应用,因为没有服务器端就无法接收授权码。
1.3密码模式
下图是密码模式交互图:
①资源拥有者将用户名、密码发送给客户端
②客户端拿着资源拥有者的用户名、密码向授权服务器请求令牌(access_token
),请求如下:http://localhost:3001/oauth/token? client_id=c1&client_secret=123&grant_type=password&username=admin&password=admin
;只支持POST
请求。
参数列表如下:
- client_id:客户端准入标识
- client_secret:客户端秘钥
- grant_type:授权类型,
password
表示密码模式 - username:资源拥有者用户名
- password:资源拥有者密码
③授权服务器将令牌(access_token
)发送给client
注:这种模式意味着直接将用户敏感信息泄漏给了client
,因此这就说明这种模式只能用于client
是我们自己开发的情况下。因此密码模式一般用于我们自己开发的,第一方原生App
或第一方单页面应用。
1.4客户端模式
下图是客户端模式交互图:
①客户端向授权服务器发送自己的身份信息,并请求令牌(access_token
)
②确认客户端身份无误后,将令牌(access_token)发送给client,请求如下:http://localhost:3001/oauth/token?client_id=c1&client_secret=123&grant_type=client_credentials
,支持POST
请求
参数列表如下:
- client_id:客户端准入标识。
- client_secret:客户端秘钥。
- grant_type:授权类型,填写
client_credentials
表示客户端模式
注:这种模式是最方便但最不安全的模式。因此这就要求我们对client
完全的信任,而client
本身也是安全的。因此这种模式一般用来提供给我们完全信任的服务器端服务。比如,合作方系统对接,拉取一组用户信息。
二、资源服务器
代码和环境搭建忽略,详情见:https://github.com/hucheng1997/security-oauth2
2.1 资源服务器配置
资源服务器配置类继承ResourceServerConfigurerAdapter
重写configure()
方法:
public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer {
public ResourceServerConfigurerAdapter() {}
public void configure(ResourceServerSecurityConfigurer resources){}
public void configure(HttpSecurity http){}
}
参数为ResourceServerSecurityConfigurer
的configure()
中主要配置:
- tokenServices:
ResourceServerTokenServices
类的实例,用来实现令牌服务 - tokenStore:
TokenStore
类的实例,指定令牌如何访问,与tokenServices
配置可选 - resourceId:这个资源服务的
ID
,这个属性是可选的,但是推荐设置并在授权服务中进行验证。 - 其他的拓展属性例如
tokenExtractor
令牌提取器用来提取请求中的令牌。
参数为HttpSecurity
的configure()
中主要配置:
- 请求匹配器,用来设置需要进行保护的资源路径,默认的情况下是保护资源服务的全部路径。
- 通过
http.authorizeRequests()
来设置受保护资源的访问规则 - 其他的自定义权限保护规则通过
HttpSecurity
来进行配置。
@EnableResourceServer 注解自动增加了一个类型为OAuth2AuthenticationProcessingFilter
的过滤器链。
2.2 测试
申请令牌:
访问资源:
使用错误的token
访问资源: