文章目录

    • 1. OAuth2介绍
    • 2. OAuth2的四种授权模式
      • ①:授权码模式
      • ②:密码模式
      • ③:简化(隐式)模式
      • ④:客户端模式
    • 3. token的携带方式
    • 4. token的自动续期 refresh token

 

        

1. OAuth2介绍

        OAuth2并不是一个框架,而是一个关于授权(authorization)的开放网络标准,是一个授权协议!OAuth在全世界得到广泛应用,目前的版本是2.0版。OAuth2的作用就是让 客户端(应用程序) 安全可控地获取"用户"的授权,与服务提供商(比如微信、微博)进行数据交互。

OAuth2的基本概念

  • (1)Third-party application:第三方应用程序,又称"客户端"(client),即我们自己的应用,比如京东app。
  • (2)HTTP service:HTTP服务提供商,简称"服务提供商",比如使用微信登录,那么微信就是服务提供商!
  • (3)Resource Owner:资源所有者,又称"用户"(user)。
  • (4)User Agent:用户代理,比如浏览器。
  • (5)Authorization server:授权服务器,即服务提供商专门用来处理认证授权的服务器。
  • (6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与授权服务器,可以是同一台服务器,也可以是不同的服务器。

令牌token与密码的区别?

  • 令牌token是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。
  • 令牌token可以被数据所有者撤销,会立即失效。密码一般不允许被他人撤销。
  • 令牌token有权限范围(scope)。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

用令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全,这就是OAuth 2.0 的优点。
        

2. OAuth2的四种授权模式

        OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权类型,即四种颁发令牌的方式,适用于不同的互联网场景。

  • 授权码模式:authorization_code
  • 密码模式:password
  • 简化(隐式)模式:implicit
  • 客户端模式:client_credentials

        不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了证明应用是可信的,防止令牌被滥用!没有备案过的第三方应用,是不会拿到令牌的。

        以下几种授权模式,都是结合Spring Security OAuth2这样一个安全框架来解释的,点击查看 Spring Security OAuth2 的配置和使用!!!!
        

①:授权码模式

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

授权码模式的步骤如下:

  • (1)用户 在 A 应用登录中选择微信登录,点击微信登录图标后会跳转到授权服务器 B,请求用户授权。
    下面就是 A 应用跳转 授权服务器 B 的一个示意链接。
    http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://www.baidu.com&scope=all
    Url参数释义如下:

    • response_type:表示授权类型,必选项,此处的值固定为"code",授权码模式
    • client_id:表示客户端的ID,必选项
    • redirect_uri:表示重定向URI,可选项
    • scope:表示申请的权限范围,可选项
    • state:表示客户端的当前状态,可以指定任意值,授权服务器会原封不动地返回这个值。
      Outh2协议有哪四种授权模式?_java
  • (2)上述url会返回一个二维码,会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务器 B 就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码code,就像下面这样。注意:本测试是在IE浏览器上测试,chrome浏览器可能无法返回!
    Outh2协议有哪四种授权模式?_java_02

  • (3)A 应用拿到授权码以后,就可以在回调地址的后端服务器中向 授权服务器B请求token令牌(url请求地址:http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client&client_secret=123123&redirect_uri=http://www.baidu.com&scope=all&code=taYiM4)。 此行为在服务端发生,用户不可见,安全性好!
    url请求地址各参数解释如下:

    • client_id=CLIENT_ID
    • client_secret=CLIENT_SECRET # client_id和client_secret用来让 B 确认 A 的身份,client_secret参数是保密的,因此只能在后端发请求
    • grant_type=authorization_code # 采用的授权方式是授权码
    • code=AUTHORIZATION_CODE # 上一步拿到的授权码
    • redirect_uri=CALLBACK_URL # 令牌颁发后的回调网址

    Outh2协议有哪四种授权模式?_java_03

  • (4)此时请求携带token标识,就可正常访问其他接口
    Outh2协议有哪四种授权模式?_java_04
            

②:密码模式

        密码模式也是比较常用的,在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分 或者自己微服务内部的系统。适用场景:自家公司搭建的授权服务器

  • (1)由于对A应用极度信任,所以A应用就能知道账号、密码,请求时根据账号密码直接向授权服务器B请求token。请求url:http://localhost:8080/oauth/token?username=fox&password=123456&grant_type=password&client_id=client&client_secret=123123&scope=all
    注意这里的授权模式为密码模式:grant_type=password

  • (2)授权服务器B验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 应用因此拿到令牌。
    Outh2协议有哪四种授权模式?_java_05
            

③:简化(隐式)模式

        简化(隐式)模式适用于纯前端应用,允许直接向前端颁发令牌,这种方式没有授权码这个中间步骤,所以称为(授权码)“隐藏式”(implicit

        简化模式不通过第三方应用程序的服务器,直接在浏览器中向授权服务器申请令牌,跳过了"授权码"这个步骤,所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

        这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

步骤如下:

  • (1)A应用请求授权服务器B,返回一个授权二维码,等待用户授权。请求url:http://localhost:8080/oauth/authorize?client_id=client&response_type=token&scope=all&redirect_uri=http://www.baidu.com
    url解析:

    • response_type=token  # response_type参数为token,表示要求直接返回令牌
    • client_id=CLIENT_ID # 应用id
    • redirect_uri=CALLBACK_URL # 重定向url
    • scope=read # 只读模式
  • (2)用户点击授权,授权服务器B回调redirect_uri并且把令牌作为 URL 参数,传给 A应用。注意连接符是#

     //回调地址
     https://a.com/callback#token=6743abeb-34db-4353-805f-5d6f71c68ca4
    

        

④:客户端模式

        客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行授权。一般用来提供给我们完全信任的服务器端服务。

步骤如下:

  • (1)客户端向授权服务器进行身份认证,并要求一个访问令牌 token。请求url:http://localhost:8080/oauth/token?grant_type=client_credentials&scope=all&client_id=client&client_secret=123123
    注意授权模式变更为:客户端模式 grant_type=client_credentials
  • (2)授权服务器验证client_idclient_secret通过后,直接返回令牌。
    Outh2协议有哪四种授权模式?_java_06
            

3. token的携带方式

在拿到token之后,就可以访问系统的资源了!只需要在请求时携带上token即可!携带方式有两种

  • 加在请求参数上:这种方式token是暴露的,不常用
    Outh2协议有哪四种授权模式?_java_07

  • 加在请求头上,隐藏了token,是常用的方式。注意:这种方式需要带上token类型
    Outh2协议有哪四种授权模式?_java_08
    请求结果:
    Outh2协议有哪四种授权模式?_java_09

        

4. token的自动续期 refresh token

问题:为什么要有token的刷新?

        如果用户登录了网站,浏览到一半,token过期了,这样用户还要重新再走一次授权、登录流程,在申请一个新的令牌,才能继续访问。这种体验显然是极差的,为了解决这个问题,OAuth 2.0 实现了token的自动更新,或者说自动续期

        具体方法是:授权服务器 B 颁发令牌的时候,一次性颁发两个令牌,一个用于获取token(access_token),另一个用于刷新token(refresh token )。token令牌到期前,使用 refresh token 发一个请求,去更新快要过期的token,实现token的自动续期。

刷新token的url地址如下http://localhost:8080/oauth/token?grant_type=refresh_token&client_id=client&client_secret=123123&refresh_token=c75dfe34-9f3c-46a3-b13d-8ffdd3785473

注意:授权类型为刷新token类型 grant_type=refresh_token
Outh2协议有哪四种授权模式?_java_10

需要注意的是:

  • 默认情况下,refresh_token只能使用一次,刷新一次后,refresh_token失效
    Outh2协议有哪四种授权模式?_java_11

  • 如果想要保持refresh_token一直有效,就是说一个refresh_token可以刷新无数次,则需要把配置reuseRefreshTokens(true),保持其重复使用!

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            
            endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
                    .tokenStore(tokenStore)  //指定token存储到redis
                    .reuseRefreshTokens(true)  //为true,refresh_token可重复使用。默认为false
                    .userDetailsService(userService) //刷新令牌授权包含对用户信息的检查
                    .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST); //支持GET,POST请求
        }