简介
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。本文重点讲解Spring Boot项目对OAuth2进行的实现,如果你对OAuth2不是很了解,你可以先理解 OAuth 2.0 - 阮一峰,这是一篇对于oauth2很好的科普文章。
OAuth2概述
oauth2根据使用场景不同,分成了4种模式
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
在项目中我们通常使用授权码模式,也是四种模式中最复杂的,通常网站中经常出现的微博,qq第三方登录,都会采用这个形式。
Oauth2授权主要由两部分组成:
- Authorization server:认证服务
- Resource server:资源服务
在实际项目中以上两个服务可以在一个服务器上,也可以分开部署。下面结合spring boot来说明如何使用。
快速上手
之前的文章已经对 Spring Security 进行了讲解,这一节对涉及到 Spring Security 的配置不详细讲解。若不了解 Spring Security 先移步到 Spring Boot Security 详解。
建表
客户端信息可以存储在内存、redis和数据库。在实际项目中通常使用redis和数据库存储。本文采用数据库。Spring 0Auth2 己经设计好了数据库的表,且不可变。表及字段说明参照:Oauth2数据库表说明 。
创建0Auth2数据库的脚本如下:
1 | DROP TABLE IF EXISTS `clientdetails`; |
为了测试方便,我们先插入一条客户端信息。
1 | INSERT INTO `oauth_client_details` VALUES ('dev', '', 'dev', 'app', 'password,client_credentials,authorization_code,refresh_token', 'http://www.baidu.com', '', 3600, 3600, '{\"country\":\"CN\",\"country_code\":\"086\"}', 'false'); |
用户、权限、角色用到的表如下:
1 | DROP TABLE IF EXISTS `user`; |
项目结构
1 | resources |
关键代码
pom.xml
1 | <dependency> |
SecurityConfig
支持password模式要配置AuthenticationManager
1 |
|
AuthorizationServerConfiguration 认证服务器配置
1 | /** |
ResourceServerConfig 资源服务器配置
1 | /** |
关键代码就是这些,其他类代码参照后面提供的源码地址。
验证
密码授权模式
[ 密码模式需要参数:username , password , grant_type , client_id , client_secret ]
请求token
1 | curl -X POST -d "username=admin&password=123456&grant_type=password&client_id=dev&client_secret=dev" http://localhost:8080/oauth/token |
返回
1 | { |
不携带token访问资源,
1 | curl http://localhost:8080/hi\?name\=zhangsan |
返回提示未授权
1 | { |
携带token访问资源
1 | curl http://localhost:8080/hi\?name\=zhangsan\&access_token\=164471f7-6fc6-4890-b5d2-eb43bda3328a |
返回正确
1 | hi , zhangsan |
刷新token
1 | curl -X POST -d 'grant_type=refresh_token&refresh_token=23503bc7-4494-4795-a047-98db75053374&client_id=dev&client_secret=dev' http://localhost:8080/oauth/token |
返回
1 | { |
客户端授权模式
[ 客户端模式需要参数:grant_type , client_id , client_secret ]
请求token
1 | curl -X POST -d "grant_type=client_credentials&client_id=dev&client_secret=dev" http://localhost:8080/oauth/token |
返回
1 | { |
授权码模式
获取code
浏览器中访问如下地址:
1 | http://localhost:8080/oauth/authorize?response_type=code&client_id=dev&redirect_uri=http://www.baidu.com |
跳转到登录页面,输入账号和密码进行认证:
认证后会跳转到授权确认页面(oauth_client_details 表中 “autoapprove” 字段设置为true 时,不会出授权确认页面):
确认后,会跳转到百度,并且地址栏中会带上我们想得到的code参数:
通过code换token
1 | curl -X POST -d "grant_type=authorization_code&code=qS03iu&client_id=dev&client_secret=dev&redirect_uri=http://www.baidu.com" http://localhost:8080/oauth/token |
返回
1 | { |
参考
https://segmentfault.com/a/1190000012260914
https://stackoverflow.com/questions/28537181/spring-security-oauth2-which-decides-security
源码
https://github.com/gf-huanchupk/SpringBootLearning/tree/master/springboot-security-oauth2