目录
1、OAuth2基本概念可以参考 OAuth2.0最简向导 (iocoder.cn)
一、概述
OAuth2是一个授权框架。用来授权第三方应用获取数据,是目前最流行的授权机制。
1、OAuth2基本概念可以参考 OAuth2.0最简向导 (iocoder.cn)
2、OAuth2 主要流程
- 用户在客户应用点击第三方应用,请求第三方应用授权访问。
- 第三方应用授权服务器同意客户应用授权,返回授权码。
- 客户应用使用授权码向授权服务器申请令牌(token)。
- 授权服务器对客户应用进行身份验证,验证通过后发放令牌(token)。
- 客户应用就可以带着这个令牌(token),去访问资源服务器的api。
- 资源服务器校验客户应用带着的令牌(token),校验通过,返回访问的api数据信息。
3、OAuth2 应用场景
网易云第三方登录(QQ、微信、微博等)。实际生活当中许多地方都会用到第三方登录,进行授权后,对其资源进行访问。
用户请求第三方应用进行授权
实际的流程如下:
4、OAuth2 授权模式(4种)
OAuth 协议的授权模式共分为 4 种,分别说明如下:
授权码模式:授权码模式(authorization code)是功能最完整、流程最严谨的授权模式。它的特点就是通过客户端的服务器与授权服务器进行交互,国内常见的第三方平台登录功能基本都是使用这种模式。(最正统的方式,也是目前绝大多数系统所采用的)(支持refresh token) (用在服务端应用之间)
简化模式:简化模式不需要客户端服务器参与,直接在浏览器中向授权服务器中请令牌,一般若网站是纯静态页面,则可以采用这种方式。(为web浏览器应用设计)(不支持refresh token) (用在移动app或者web app,这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)
密码模式:密码模式是用户把用户名密码直接告诉客户端,客户端使用这些信息向授权服务器中请令牌。这需要用户对客户端高度信任,例如客户端应用和服务提供商是同一家公司。(为遗留系统设计) (支持refresh token)
客户端模式:客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权。严格来说,客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。(为后台api服务消费者设计) (不支持refresh token) (为后台api服务消费者设计)
二、使用
对于 Spring Security OAuth2 的配置,大体来说,就是两步:
- 配置授权服务器( AuthorizationServer )
- 配置资源服务器( ResourceServer )
1、导入maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
SpringBoot 的版本为 1.5.16.RELEASE ,所以使用的 Spring Security 的版本为 4.2.8.RELEASE ,Spring Security OAuth2 的版本为 2.2.0.15.RELEASE
2、配置资源服务器
资源服务器一般提供Api服务,例如订单、商品服务等。考虑到让整个示例更加简单,本文先将它和授权服务器放在一个 Maven 项目中。
1.编写controller类
/**
* 资源服务器访问示例
*/
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
2.编写资源服务器配置文件
@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 对 "/api/**" 开启认证
.anyRequest()
.authenticated()
.and()
.requestMatchers()
.antMatchers("/api/**");
}
}
@Configuration 注解:保证 OAuth2ResourceServer 能够被 SpringBoot 扫描到配置。 @EnableResourceServer 注解:开启资源服务器。
@EnableResourceServer继承( extends ) ResourceServerConfigurerAdapter 类,并覆写 #configure(HttpSecurity http) 方法,配置对 HTTP 请求中,匹配 /api/**" 路径,开启认证的验证。( @EnableResourceServer导入了ResourceServerConfiguration配置类,该配置类继承了WebSecurityConfigurerAdapter,拥有了http security的相关能力。 )
3、配置授权服务器
这儿就用到了上面所说的四种授权模式:
- 授权码模式
- 简化模式
- 密码模式
- 客户端模式
1.授权码模式
1.1 配置授权服务器
// 授权服务器配置
@Configuration
@EnableAuthorizationServer //开启授权服务器
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory() // 基于内存,实际当中应该存放数据库
.withClient("mobai").secret("123") // Client 账号、密码。
.redirectUris("http://localhost:9001/callback") // 配置回调地址,选填。
.authorizedGrantTypes("authorization_code") // 授权码模式
.scopes("user_info", "role_info"); // 可授权的 Scope
}
1.2 配置springSecurity登录账号
在application.yml中配置springSecurity登录账号密码。实际当中登录账号是放在数据库当中的。
security:
user:
name: admin
password: admin
1.3 启动项目获取授权码
访问 http://localhost:8080/oauth/authorize?client_id=mobai&redirect_uri=http://localhost:9001/callback&response_type=code&scope=user_info 获取
-client_id :必传,为我们在 OAuth2AuthorizationServer 中配置的 Client 的编号。
redirect_url :可选,回调地址。当然,如果 client_id 对应的 Client 未配置 redirectUris 属性,会报错。实际项目当中,会在后端编写一个接收授权码的接口进行授权码接收,或者跳转到对应的页面(回调地址)进行授权码接收,前端进行地址拦截,再进行下一步处理(如登录)。
response_type :必传,返回结果为授权码。
scope :可选,申请授权的 Scope 。如果多个,使用逗号分隔。
state : 可选,表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这 个值。未在上述 URL 中体现出来。
访问该地址后,会跳至 springSecurity 登录页面,输入上面配置的账号密码 admin/amdin,跳至oauth授权确认页面,如下: