JWT和OAuth2比较?

要比较JWT和OAuth2?首先要明白一点就是,这两个根本没有可比性,是两个完全不同的东西。

  • JWT是一种认证协议
            JWT提供了一种用于发布接入令牌(Access Token),并对发布的签名接入令牌进行验证的方法。令牌(Token)本身包含了一系列声明,应用程序可以根据这些声明限制用户对资源的访问。
  • OAuth2是一种授权框架
            另一方面,OAuth2是一种授权框架,提供了一套详细的授权机制(指导)。用户或应用可以通过公开的或私有的设置,授权第三方应用访问特定资源。既然JWT和OAuth2没有可比性,为什么还要把这两个放在一起说呢?实际中确实会有很多人拿JWT和OAuth2作比较。标题里把这两个放在一起,确实有误导的意思。很多情况下,在讨论OAuth2的实现时,会把JSON Web Token作为一种认证机制使用。这也是为什么他们会经常一起出现。

先来搞清楚JWT和OAuth2究竟是干什么的~

JSON Web Token (JWT)

JWT在标准中是这么定义的:

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).
-RFC7519 https://tools.ietf.org/html/rfc7519

JWT是一种安全标准。基本思路就是用户提供用户名和密码给认证服务器,服务器验证用户提交信息信息的合法性;如果验证成功,会产生并返回一个Token(令牌),用户可以使用这个token访问服务器上受保护的资源。一个token的例子:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
一个token包含三部分:
header.claims.signature
了安全的在url中使用,所有部分都 base64 URL-safe进行编码处理。

Header头部分
        头部分简单声明了类型(JWT)以及产生签名所使用的算法。

{  "alg" : "AES256",  "typ" : "JWT"}

Claims声明


声明部分是整个token的核心,表示要发送的用户详细信息。有些情况下,我们很可能要在一个服务器上实现认证,然后访问另一台服务器上的资源;或者,通过单独的接口来生成token,token被保存在应用程序客户端(比如浏览器)使用。
一个简单的声明(claim)的例子:

{  "sub": "1234567890",  "name": "John Doe",  "admin": true}

Signature签名        签名的目的是为了保证上边两部分信息不被篡改。如果尝试使用Bas64对解码后的token进行修改,签名信息就会失效。一般使用一个私钥(private key)通过特定算法对Header和Claims进行混淆产生签名信息,所以只有原始的token才能于签名信息匹配。
        这里有一个重要的实现细节。只有获取了私钥的应用程序(比如服务器端应用)才能完全认证token包含声明信息的合法性。所以,永远不要把私钥信息放在客户端(比如浏览器)。

OAuth2是什么?

相反,OAuth2不是一个标准协议,而是一个安全的授权框架。它详细描述了系统中不同角色、用户、服务前端应用(比如API),以及客户端(比如网站或移动App)之间怎么实现相互认证。

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.
-RFC6749 https://tools.ietf.org/html/rfc6749

这里简单说一下涉及到的基本概念。Roles角色
应用程序或者用户都可以是下边的任何一种角色:

  • 资源拥有者

  • 资源服务器

  • 客户端应用

  • 认证服务器

Client Types客户端类型
这里的客户端主要指API的使用者。它可以是的类型:

  • 私有的

  • 公开的

Client Profile客户端描述
OAuth2框架也指定了集中客户端描述,用来表示应用程序的类型:

  • Web应用

  • 用户代理

  • 原声应用

Authorization Grants认证授权
认证授权代表资源拥有者授权给客户端应用程序的一组权限,可以是下边几种形式:

  • 授权码

  • 隐式授权

  • 资源拥有者密码证书

  • 客户端证书

  • Endpoints终端

OAuth2框架需要下边几种终端:

  • 认证终端

  • Token终端

  • 重定向终端

从上边这些应该可以看出,OAuth2定义了一组相当复杂的规范。

使用HTTPS保护用户密码

在进一步讨论OAuth2和JWT的实现之前,有必要说一下,两种方案都需要SSL安全保护,也就是对要传输的数据进行加密编码。
        安全地传输用户提供的私密信息,在任何一个安全的系统里都是必要的。否则任何人都可以通过侵入私人wifi,在用户登录的时候窃取用户的用户名和密码等信息。一些重要的实施考虑
在做选择之前,参考一下下边提到的几点。时间投入
          OAuth2是一个安全框架,描述了在各种不同场景下,多个应用之间的授权问题。有海量的资料需要学习,要完全理解需要花费大量时间。甚至对于一些有经验的开发工程师来说,也会需要大概一个月的时间来深入理解OAuth2。这是个很大的时间投入。相反,JWT是一个相对轻量级的概念。可能花一天时间深入学习一下标准规范,就可以很容易地开始具体实施。出现错误的风险
        OAuth2不像JWT一样是一个严格的标准协议,因此在实施过程中更容易出错。尽管有很多现有的库,但是每个库的成熟度也不尽相同,同样很容易引入各种错误。在常用的库中也很容易发现一些安全漏洞。
        当然,如果有相当成熟、强大的开发团队来持续OAuth2实施和维护,可以一定成都上避免这些风险。社交登录的好处
        在很多情况下,使用用户在大型社交网站的已有账户来认证会方便。
        如果期望你的用户可以直接使用Facebook或者Gmail之类的账户,使用现有的库会方便得多。

结论

做结论前,我们先来列举一下  JWT和OAuth2的主要使用场景。

JWT使用场景

无状态的分布式API

JWT的主要优势在于使用无状态、可扩展的方式处理应用中的用户会话。服务端可以通过内嵌的声明信息,很容易地获取用户的会话信息,而不需要去访问用户或会话的数据库。在一个分布式的面向服务的框架中,这一点非常有用。
        但是,如果系统中需要使用黑名单实现长期有效的token刷新机制,这种无状态的优势就不明显了。优势

  • 快速开发

  • 不需要cookie

  • JSON在移动端的广泛应用

  • 不依赖于社交登录

  • 相对简单的概念理解

限制

  • Token有长度限制

  • Token不能撤销

  • 需要token有失效时间限制(exp)

  • OAuth2使用场景

在作者看来两种比较有必要使用OAuth2的场景:

外包认证服务器

上边已经讨论过,如果不介意API的使用依赖于外部的第三方认证提供者,你可以简单地把认证工作留给认证服务商去做。
        也就是常见的,去认证服务商(比如facebook)那里注册你的应用,然后设置需要访问的用户信息,比如电子邮箱、姓名等。当用户访问站点的注册页面时,会看到连接到第三方提供商的入口。用户点击以后被重定向到对应的认证服务商网站,获得用户的授权后就可以访问到需要的信息,然后重定向回来。优势

  • 快速开发

  • 实施代码量小

  • 维护工作减少

大型企业解决方案

如果设计的API要被不同的App使用,并且每个App使用的方式也不一样,使用OAuth2是个不错的选择。
        考虑到工作量,可能需要单独的团队,针对各种应用开发完善、灵活的安全策略。当然需要的工作量也比较大!这一点,OAuth2的作者也指出过:

To be clear, OAuth 2.0 at the hand of a developer with deep understanding of web security will likely result is a secure implementation. However, at the hands of most developers – as has been the experience from the past two years – 2.0 is likely to produce insecure implementations.
hueniverse - OAuth 2.0 and the Road to Hell

优势

  • 灵活的实现方式

  • 可以和JWT同时使用

  • 可针对不同应用扩展

进一步

    • http://jwt.io - JWT官方网站,也可以查看到使用不同语言实现的库的状态。

    • http://oauth.net/2/ OAuth2官方网站, 也也可以查看到使用不同语言实现的库的状态。

    • OAuth 2 tutorials - Useful overview of how OAuth 2 works

    • Oauth2 Spec issues Eran Hammer’s (推进OAuth标准的作者) views on what went wrong with the OAuth 2 spec process. Whatever your own opinion, good to get some framing by someone who understand’s key aspects of what make a security standard successful.

    • Thoery and implemnetation: with Laravel and Angular Really informative guide to JWT in theory and in practice for Laravel and Angular.

OAuth2和JWT - 如何设计安全的API?的更多相关文章

  1. OAuth 2和JWT - 如何设计安全的API?

    OAuth 2和JWT - 如何设计安全的API? Moakap译,原文 OAuth 2 VS JSON Web Tokens: How to secure an API 本文会详细描述两种通用的保证 ...

  2. 使用JWT设计SpringBoot项目api接口安全服务

    转载直: 使用JWT设计SpringBoot项目api接口安全服务

  3. 如何构建和设计以确保 API 的安全性

    如何构建和设计以确保 API 的安全性 面对常见的OWASP十大威胁.未经授权的访问.拒绝服务攻击.以及窃取机密数据等类型的攻击,企业需要使用通用的安全框架,来保护其REST API,并保证良好的用户 ...

  4. SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

  5. 使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

  6. Atitit.论图片类型 垃圾文件的识别与清理  流程与设计原则 与api概要设计 v2 pbj

    Atitit.论图片类型 垃圾文件的识别与清理  流程与设计原则 与api概要设计 v2 pbj 1. 俩个问题::识别垃圾文件与清理策略1 2. 如何识别垃圾图片1 2.1. 体积过小文件<1 ...

  7. 如何设计优秀的API(转)

    到目前为止,已经负责API接近两年了,这两年中发现现有的API存在的问题越来越多,但很多API一旦发布后就不再能修改了,即时升级和维护是必须的.一旦API发生变化,就可能对相关的调用者带来巨大的代价, ...

  8. 队列链式存储 - 设计与实现 - API函数

    队列相关基础内容参我的博文:队列顺序存储 - 设计与实现 - API函数 队列也是一种特殊的线性表:可以用线性表链式存储来模拟队列的链式存储. 主要代码: // linkqueue.h // 队列链式 ...

  9. 队列顺序存储 - 设计与实现 - API函数

    队列是一种特殊的线性表 队列仅在线性表的两端进行操作 队头(Front):取出数据元素的一端 队尾(Rear):插入数据元素的一端 队列不允许在中间部位进行操作! queue常用操作 销毁队列 清空队 ...

随机推荐

  1. Spark RDD学习

    RDD(弹性分布式数据集)是Spark的核心抽象.它是一组元素,在集群的节点之间进行分区,以便我们可以对其执行各种并行操作. 创建RDD的两种方式: 并行化驱动程序中的现有数据: 引用外部存储系统中的 ...

  2. MySQL时间格式TIMESTAMP和DATETIME的区别

    时区,timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化 自动更新,insert.update数据时,可以设置timestamp列自动以当前时间(CURRENT_T ...

  3. 类中的__getattr__ 与 __setattr__ 魔法方法

    1.__getattr__ 当我们访问一个不存在的属性的时候,会抛出异常,提示我们不存在这个属性.而这个异常就是__getattr__方法抛出的,其原因在于他是访问一个不存在的属性的最后落脚点,作为异 ...

  4. Solution -「WF2011」「BZOJ #3963」MachineWorks

    \(\mathcal{Description}\)   Link.   给定你初始拥有的钱数 \(C\) 以及 \(N\) 台机器的属性,第 \(i\) 台有属性 \((d_i,p_i,r_i,g_i ...

  5. Solution -「JOISC 2021」「LOJ #3495」聚会 2

    \(\mathcal{Description}\)   Link.   给定一棵含 \(n\) 个结点的树.称点集 \(S\) 到结点 \(u\) 的会合距离为 \(\sum_{v\in S}\ope ...

  6. java中的代码块(初始化块)

    介绍 代码块又叫初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{ } 包围起来,但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不通过对象或类显示调用,而是加载类 ...

  7. 《操作系统导论》第14章 | 内存操作API

    内存类型 在运行一个C程序的时候,会分配两种类型的内存.第一种称为栈内存,它的申请和释放操作是编译器来隐式管理的,所以有时也称为自动内存.假设需要在func()函数中为一个整形变量x申请空间,我们只需 ...

  8. web开发 小方法1-禁止横向滚动

    最近学了学做了个公司的网站  总结了一些小方法 比如取消横向滚动条并禁止的横向滚动 这样就可以吧超出的切掉让网页更和谐 在body 标签 body{ text-align: center; overf ...

  9. Java中邮件发送session.getDefaultInstance和getInstance的区别

    假设你想要同时用两个邮箱分别给再给两个邮箱发送邮件时,你就需要创建两个java.mail.Session对象,这时候你用getDefaultInstance的话会发现第二个Session对象和第一个对 ...

  10. Fedora 30的升级方法

    Fedora 30 已经发布了.你可能希望将系统升级到最新版本的 Fedora.Fedora 工作站版本有图形化升级的方法.另外,Fedora 也提供了一个命令行方法,用于将 Fedora 29 升级 ...