简介

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数据库的脚本如下:



DROP



为了测试方便,我们先插入一条客户端信息。



INSERT



用户、权限、角色用到的表如下:



DROP



项目结构



resources
|____templates
| |____login.html
| |____application.yml
java
|____com
| |____gf
| | |____SpringbootSecurityApplication.java
| | |____config
| | | |____SecurityConfig.java
| | | |____MyFilterSecurityInterceptor.java
| | | |____MyInvocationSecurityMetadataSourceService.java
| | | |____ResourceServerConfig.java
| | | |____WebResponseExceptionTranslateConfig.java
| | | |____AuthorizationServerConfiguration.java
| | | |____MyAccessDecisionManager.java
| | |____entity
| | | |____User.java
| | | |____RolePermisson.java
| | | |____Role.java
| | |____mapper
| | | |____PermissionMapper.java
| | | |____UserMapper.java
| | | |____RoleMapper.java
| | |____controller
| | | |____HelloController.java
| | | |____MainController.java
| | |____service
| | | |____MyUserDetailsService.java



关键代码

pom.xml



<dependency>



SecurityConfig

支持password模式要配置AuthenticationManager



@Configuration



AuthorizationServerConfiguration 认证服务器配置



/**



ResourceServerConfig 资源服务器配置



/**



关键代码就是这些,其他类代码参照后面提供的源码地址。

验证

密码授权模式

[ 密码模式需要参数:username , password , grant_type , client_id , client_secret ]

请求token



curl -X POST -d "username=admin&password=123456&grant_type=password&client_id=dev&client_secret=dev" http://localhost:8080/oauth/token



返回



{



不携带token访问资源,



curl http://localhost:8080/hi?name=zhangsan



返回提示未授权



{



携带token访问资源



curl http://localhost:8080/hi?name=zhangsan&access_token=164471f7-6fc6-4890-b5d2-eb43bda3328a



返回正确



hi , zhangsan



刷新token



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



返回



{
    "access_token": "ef53eb01-eb9b-46d8-bd58-7a0f9f44e30b",
    "token_type": "bearer",
    "refresh_token": "23503bc7-4494-4795-a047-98db75053374",
    "expires_in": 3599,
    "scope": "app"
}



客户端授权模式

[ 客户端模式需要参数:grant_type , client_id , client_secret ]

请求token



curl -X POST -d "grant_type=client_credentials&client_id=dev&client_secret=dev" http://localhost:8080/oauth/token



返回



{



授权码模式

获取code

浏览器中访问如下地址:



http://localhost:8080/oauth/authorize?response_type=code&client_id=dev&redirect_uri=http://www.baidu.com



跳转到登录页面,输入账号和密码进行认证:




springbootAK和账密防泄漏_springbootAK和账密防泄漏


认证后会跳转到授权确认页面(oauth_client_details 表中 “autoapprove” 字段设置为true 时,不会出授权确认页面):


springbootAK和账密防泄漏_项目服务接口设计_02


确认后,会跳转到百度,并且地址栏中会带上我们想得到的code参数:


springbootAK和账密防泄漏_java_03


通过code换token


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