笔者最近花了点时间研究Oauth2原理,基于spring写了一些demo用于实践探索,深深体会到
Spring Security Oauth2
框架的便利,框架帮我们封装太多了底层实现,所以使用起来非常方便,除了可以为第三方应用提供授权,也可以作为应用的登录框架。
文章基于Spring Security Oauth2.0
授权码模式实践,采用SpringBoot
搭建Demo讲述基本使用过程。
概述
简单来说Oauth2是一个授权协议,用于为第三方访问服务提供特定的授权流程。
它的最终目的是为第三方应用颁发一个有时效性的令牌 token。使得第三方应用能够通过该令牌获取相关的资源。常见的场景就是:第三方登录。当你想要登录某个论坛,但没有账号,而这个论坛接入了如 QQ、Facebook 等登录功能,在你使用 QQ 登录的过程中就使用的OAuth 2.0
协议。
在进入正式实践章节之前,有必要先了解下Oauth2的关键知识点。关于Oauth2协议更多详细内容,可以参考10 分钟理解什么是 OAuth 2.0 协议,是一个比较好的科普文章。
Oauth2.0
协议中的几个角色
resource owner
资源所有者,能够允许访问受保护资源的实体。如果是个人,被称为end-user
。resource server
资源服务器,受保护资源的服务器,即访问该服务器需要获取授权或许可。client
客户端,使用资源所有者的授权代表资源所有者发起对受保护资源的请求的应用程序。如:web网站,移动应用等。authorization server
,授权服务器,能够向客户端client
颁发令牌。User-Agent
,用户代理,帮助资源所有者与客户端沟通的工具,一般为 web 浏览器,移动 APP 等。
几个角色间的认证步骤
+--------+ +---------------+ | |--(A)- 请求用户授权许可---- > | Resource | | | | Owner | | |<-(B)-- 授权许可 ----------- | | | | +---------------+ | | | | +---------------+ | |--(C)-- 获取token ----------> | Authorization | | Client | | Server | | |<-(D)----- 发放token ----------| | | | +---------------+ | | | | +---------------+ | |--(E)----- token访问资源 ------>| Resource | | | | Server | | |<-(F)--- 返回受保护的资源 ------| | +--------+ +---------------+
Spring Security Oauth2.0
几个端点的作用
启动项目时会有这发布这些端点,用于Oauth2
交互逻辑:
- 根据用户认证获得授权码code
AuthorizationEndpoint
{[/oauth/authorize]}
{[/oauth/authorize],methods=[POST]
- 客户端根据授权码code获取令牌token
TokenEndpoint
{[/oauth/token],methods=[GET]}
{[/oauth/token],methods=[POST]}
- 可以用于远程解码令牌
CheckTokenEndpoint
{[/oauth/check_token]}
- 显示授权服务器的确认页
WhitelabelApprovalEndpoint
{[/oauth/confirm_access]}
- 显示授权服务器的错误页
WhitelabelErrorEndpoint
{[/oauth/error]}
Oauth2.0
四种授权模式
- 授权码模式(authorization code)
最常用,可用于第三方应用授权、SSO登录实现等。 - 简化模式(implicit)
一般不用 - 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
一般用于后台服务接口间的认证
实践
搭建Oauth2
应用,主要分为4个步骤:搭建认证/授权服务器、搭建资源服务器、配置SpringSercurity、客户端服务器。
以github
作为授权服务器举例说明授权码模式的流程:
- 用户访问第三方应用
A-Server
,未登录,A-Server
提供github
认证登录; - 用户点击
github
认证,跳转到github
; - 如用户在
github
未登录,跳转到github
登录页,用户输入账户密码即可完成登录,并跳转到原来的第三方应用A-Server
并得到颁布的token; - 如用户已在
github
登录,则跳转到github
确认授权页,用户点击授权后即可跳转到原来的第三方应用A-Server
并得到颁布的token
项目准备
- 建立项目
oauth-server
,引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.oauth.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>oauth-server</artifactId>
<!-- security stater -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>1.5.10.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!-- 数据库 mybatis 连接池等相关配置 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>