OAuth 2.0 学习

傻男人 1年前 ⋅ 737 阅读

OAuth 2.0 学习

一、什么是单点登录

多点登录

传统的多点登录系统中,每个站点都实现了本站专用的帐号数据库和登录模块。各站点的登录状态相互不认可,各站点需要逐一手工登录。 有两个术语含义如下:

  • 认证(authentication): 验证用户的身份;
  • 授权(authorization): 验证用户的访问权限。
单点登录

单点登录,英文是 Single Sign On,缩写为 SSO。 多个站点共用一台认证授权服务器(用户数据库和认证授权模块共用)。用户经由其中任何一个站点登录后,可以免登录访问其他所有站点。 而且,各站点间可以通过该登录状态直接交互。

二、oauth的运行流程

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

运行流程如下图,摘自RFC 6749。

  • (A)用户打开客户端以后,客户端要求用户给予授权。
  • (B)用户同意给予客户端授权。
  • (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
  • (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
  • (E)客户端使用令牌,向资源服务器申请获取资源。
  • (F)资源服务器确认令牌无误,同意向客户端开放资源。

我们是对内的系统,并不需要那么复杂的流程,所以我们看下oauth的授权模式当中的密码模式:

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          v
          |    Resource Owner
         (A) Password Credentials
          |
          v
     +---------+                                  +---------------+
     |         |>--(B)---- Resource Owner ------->|               |
     |         |         Password Credentials     | Authorization |
     | Client  |                                  |     Server    |
     |         |<--(C)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+

这里的流程相对就比较简单了:

(A)用户向客户端提供用户名和密码。

(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

(C)认证服务器确认无误后,向客户端提供访问令牌。

现在将简单的转换下思路:

  • Resource Owner:资源拥有者,拥有订单,购物车等数据的人,既用户

  • Client:客户端,浏览器

  • Authorization Server:认证服务器,也就是服务器咯。

在此A、B、C三个流程就变成了:

(A)用户在浏览器输入用户名和密码。

(B)浏览器将用户名和密码发给服务器,向后者请求令牌(token)。

(C)服务器确认无误后,返回token给用户。

三、OAuth 2.0 的四种方式

1)、授权码模式(authorization-code/Auth Code)

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

应用的场景:成功后跳转其他页面,如第三方微信登录等

这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

  • 获取code
http://localhost:9090/oauth/authorize?client_id=normal-app&response_type=code&scope=read&redirect_uri=http://139.224.247.139:8080/
  • 用code换取token
http://localhost:9090/oauth/token?code=hepL9e&grant_type=authorization_code&client_id=normal-app&redirect_uri=http://139.224.247.139:8080/&client_secret=123456&scope=read
2)、简化模式(implicit)

有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 应用的场景:不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌

3)、密码模式(password credentials)

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。

应用的场景:web页面用户名密码登录

模拟请求:
post http://localhost:8080/oauth/token?username=user_1&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456

请求正常返回的结果:

{
    "access_token": "c2340190-48f3-4291-bb17-1e4d51bcb284",
    "token_type": "bearer",
    "refresh_token": "03ee113c-a942-452a-9918-7ffe24472a7f",
    "expires_in": 40399,
    "scope": "select"
}
4)、客户端模式(client credentials)

客户端模式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 应用的场景:主要针对openapi,使用apikey和secretkey方式

post http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456
结果如下
{
    "access_token": "05a4e614-f34b-4c83-9ec1-89ea55c0afd2",
    "token_type": "bearer",
    "expires_in": 40396,
    "scope": "select"
}

HttpSecurity中关于successHandler与successForwardUrl的生效:后面的设置会覆盖掉前面的设置

常用接口

检查token有效性

配置的方法:

  • 方法一: 在继承AuthorizationServerConfigurerAdapter中的configure的方法中,添加
oauthServer.checkTokenAccess("permitAll()");
  • 方法二: 配置文件中配置
security.oauth2.authorization.check-token-access=permitAll()

请求接口示例:

get localhost:9090/oauth/check_token?token=8e9d3088-6c21-414f-b597-5ef64948d9f7

oauth_client_detail表 说明

字段名字段约束详细描述范例
client_id主键,必须唯一,不能为空用于唯一标识每一个客户端(client);注册时必须填写(也可以服务端自动生成),这个字段是必须的,实际应用也有叫app_keyOaH1heR2E4eGnBr87Br8FHaUFrA2Q0kE8HqZgpdg8Sw
resource_ids不能为空,用逗号分隔客户端能访问的资源id集合,注册客户端时,根据实际需要可选择资源id,也可以根据不同的额注册流程,赋予对应的额资源idorder-resource,pay-resource
client_secret必须填写注册填写或者服务端自动生成,实际应用也有叫app_secret, 必须要有前缀代表加密方式{bcrypt}gY/Hauph1tqvVWiH4atxteSH8sRX03IDXRIQi03DVTFGzKfz8ZtGi
scope不能为空,用逗号分隔指定client的权限范围,比如读写权限,比如移动端还是web端权限read,write / web,mobile
authorized_grant_types不能为空可选值 授权码模式:authorization_code,密码模式:password,刷新token: refresh_token, 隐式模式: implicit: 客户端模式: client_credentials。支持多个用逗号分隔password,refresh_token
web_server_redirect_uri可为空客户端重定向uri,authorization_code和implicit需要该值进行校验,注册时填写,httt://baidu.com
authorities可为空指定用户的权限范围,如果授权的过程需要用户登陆,该字段不生效,implicit和client_credentials需要ROLE_ADMIN,ROLE_USER
access_token_validity可空设置access_token的有效时间(秒),默认(606012,12小时)3600
refresh_token_validity可空设置refresh_token有效期(秒),默认(606024*30, 30填)7200
additional_information可空值必须是json格式 {"key", "value"}
autoapprovefalse/true/read/write默认false,适用于authorization_code模式,设置用户是否自动approval操作,设置true跳过用户确认授权操作页面,直接跳到redirect_urifalse

博客

SpringCloud鉴权之OAuth2.0(上篇)

https://segmentfault.com/a/1190000019772023

从零开始的Spring Security Oauth2(二)

http://blog.didispace.com/spring-security-oauth2-xjf-2/

OAuth2.0 原理流程及其单点登录和权限控制

https://blog.csdn.net/kefengwang/article/details/81213025

微服务实战(一)基于OAUTH2.0统一认证授权的微服务基础架构

https://blog.csdn.net/w1054993544/article/details/78932614

oauth2.0通过JdbcClientDetailsService从数据库读取相应的配置

https://www.cnblogs.com/charlypage/p/9383420.html

Spring Security OAuth2.0 认证协议【1】- 基本概念

https://blog.csdn.net/LawssssCat/article/details/105065992

Spring boot+Security OAuth2 爬坑日记(2)

https://blog.csdn.net/qq_31063463/article/details/83073739

Spring Cloud OAuth2 实现自定义返回格式

https://segmentfault.com/a/1190000020317220?utm_source=tag-newest

restTemplate基本的认证

restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(map.get("client_id").toString(),map.get("client_secret").toString()));


全部评论: 0

    我有话说: