关于前后端分离开发接口鉴权

前言

在项目开发中,为了提高项目开发效率,一般会选择前后端分离开发的形式,但是如果不进行身份鉴别的话,后台的接口是公开暴露的,只要访问URL便可获取到接口中的数据,这样的很不安全的。为了保证数据的安全性,我们需要设计api的鉴权机制。


常见的接口鉴权机制

1. HTTP Basic Authentication

2. session-cookie

3. Token 验证

4. OAuth(开放授权)

鉴权机制详述及场景应用

一、HTTP Basic Authentication

这种授权方式是浏览器遵守http协议实现的基本授权方式,HTTP协议进行通信的过程中,HTTP协议定义了基本认证允许HTTP服务器对客户端进行用户身份证的方法。

认证流程:

1.客户端向服务器请求数据,假设客户端尚未被验证,则客户端提供请求至服务器时,服务器会返回401返回值,提示未经授权

2.当符合http1.0或1.1规范的客户端,收到401返回值时,将会自动弹出一个登录框,要求用户输入用户名和密码

3. 用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中,加密过程是浏览器默认的行为,不需要我们人为加密,我们只需要输入用户名密码即可

4.服务器收到上述请求信息后,将请求头中的 Authorization 字段后的用户信息取出、解密,将解密后的用户名及密码与用户数据库进行比较验证,如用户名及密码正确,服务器则根据请求,将所请求资源发送给客户端

优点:

基本认证的一个优点是基本上所有流行的网页浏览器都支持基本认证。基本认证很少在可公开访问的互联网网站上使用,有时候会在小的私有系统中使用(如路由器网页管理接口)。后来的机制HTTP摘要认证是为替代基本认证而开发的,允许密钥以相对安全的方式在不安全的通道上传输。

程序员和系统管理员有时会在可信网络环境中使用基本认证,使用Telnet或其他明文网络协议工具手动地测试Web服务器。这是一个麻烦的过程,但是网络上传输的内容是人可读的,以便进行诊断。

缺点:

虽然基本认证非常容易实现,但该方案创建在以下的假设的基础上,即:客户端和服务器主机之间的连接是安全可信的。特别是,如果没有使用SSL/TLS这样的传输层安全的协议,那么以明文传输的密钥和口令很容易被拦截。该方案也同样没有对服务器返回的信息提供保护。

现存的浏览器保存认证信息直到标签页或浏览器被关闭,或者用户清除历史记录。HTTP没有为服务器提供一种方法指示客户端丢弃这些被缓存的密钥。这意味着服务器端在用户不关闭浏览器的情况下,并没有一种有效的方法来让用户注销。

HTTP基本认证的目标是提供简单的用户验证功能,其认证过程简单明了,适合于对安全性要求不高的系统或设备中,如大家所用路由器的配置页面的认证,几乎都采取了这种方式。其缺点是没有灵活可靠的认证策略,如无法提供域(domain或realm)认证功能,另外,BASE64的加密强度非常低,可以说仅能防止sohu的搜索把它搜到了。当然,HTTP基本认证系统也可以与SSL或者Kerberos结合,实现安全性能较高(相对)的认证系统。

二、session-cookie

Http协议是一个无状态的协议,服务器不会知道到底是哪一台浏览器访问了它,因此需要一个标识用来让服务器区分不同的浏览器。cookie 就是这个管理服务器与客户端之间状态的标识。

2.1 cookie

cookie 的原理是,浏览器第一次向服务器发送请求时,服务器在 response 头部设置 Set-Cookie 字段,浏览器收到响应就会设置 cookie 并存储,在下一次该浏览器向服务器发送请求时,就会在 request 头部自动带上 Cookie 字段,服务器端收到该 cookie 用以区分不同的浏览器。当然,这个 cookie 与某个用户的对应关系应该在第一次访问时就存在服务器端,这时就需要 session 了。

2.2 session

session 是会话的意思,浏览器第一次访问服务端,服务端就会创建一次会话,在会话中保存标识该浏览器的信息。它与 cookie 的区别就是 session 是缓存在服务端的,cookie则是缓存在客户端,他们都由服务端生成,为了弥补 Http 协议无状态的缺陷。

2.3 session-cookie认证

(1) 服务器在接受客户端首次访问时在服务器端创建seesion,然后保存seesion(我们可以将seesion保存在 内存中,也可以保存在redis中,推荐使用后者),然后给这个session生成一个唯一的标识字符串,然后在 响应头中种下这个唯一标识字符串。

(2) 签名。这一步通过秘钥对sessionId进行签名处理,避免客户端修改sessionId。(非必需步骤)

(3) 浏览器中收到请求响应的时候会解析响应头,然后将sessionId保存在本地cookie中,浏览器在下次http请求的请求头中会带上该域名下的cookie信息。

(4) 服务器在接受客户端请求时会去解析请求头cookie中的sessionId,然后根据这个sessionId去找服务器端保存的该客户端的session,然后判断该请求是否合法。

(5) 使用session-cookie做登录认证时,登录时存储session,退出登录时删除session,而其他的需要登录后才能操作的接口需要提前验证是否存在session,存在才能跳转页面,不存在则回到登录页面。

缺点:

(1) 认证方式局限于在浏览器中使用,cookie 是浏览器端的机制,如果在app端就无法使用 cookie。

(2) 为了满足全局一致性,最好把 session 存储在 redis 中做持久化,而在分布式环境下,我们可能需要在每个服务器上都备份,占用了大量的存储空间。

(3) 在不是 Https 协议下使用 cookie ,容易受到 CSRF 跨站点请求伪造攻击。

三、Token 验证

token 是一个令牌,浏览器第一次访问服务端时会签发一张令牌,之后浏览器每次携带这张令牌访问服务端就会认证该令牌是否有效,只要服务端可以解密该令牌,就说明请求是合法的,令牌中包含的用户信息还可以区分不同身份的用户。一般 token 由用户信息、时间戳和由 hash 算法加密的签名构成。

认证流程:

1.客户端使用用户名跟密码请求登录

2.服务端收到请求,去验证用户名与密码

3.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端

4.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者Local Storage 里

5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token

6.服务端收到请求,然后去验证客户端请求里面带着的 Token(request头部添加Authorization),如果验证成功,就向客户端返回请求的数据 ,如果不成功返回401错误码,鉴权失败。

缺点:

1.加密解密消耗使得 token 认证比 session-cookie 更消耗性能。

2.token 比 sessionId 大,更占带宽。

Token和session的区别:

1.token 认证不局限于 cookie ,这样就使得这种认证方式可以支持多种客户端,而不仅是浏览器。且不受同源策略的影响。

2.不使用 cookie 就可以规避CSRF攻击。

3.token 不需要存储,token 中已包含了用户信息,服务器端变成无状态,服务器端只需要根据定义的规则校验这个 token 是否合法就行。这也使得 token 的可扩展性更强。

JWT(JSON Web Token)

基于 token 的解决方案有许多,常用的是JWT,JWT 的原理是,服务器认证以后,生成一个 JSON 对象,这个 JSON 对象肯定不能直接传给用户,那任何人都可以篡改这个对象发送请求。因此这个 JSON 对象会被服务器端签名加密后返回给用户,返回的内容就是一张令牌,以后用户每次访问服务器端就带着这张令牌。

这个 JSON 对象可能包含的内容就是用户的信息,用户的身份以及令牌的过期时间。

JWT组成部分:

由三部分组成:Header(头部)、Payload(负载)或是 Claims(声明)、Signature(签名):

1.Header部分是一个JSON对象,描述JWT的元数据。一般描述信息为该Token的加密算法以及Token的类型。{“alg”: “HS256″,”typ”: “JWT”}的意思就是,该token使用HS256加密,token类型是JWT。这个部分基本相当于明文,它将这个JSON对象做了一个Base64转码,变成一个字符串。Base64编码解码是有算法的,解码过程是可逆的。头部信息默认携带着两个字段。

2.Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。有7个官方字段,还可以在这个部分定义私有字段。一般存放用户名、用户身份以及一些JWT的描述字段。它也只是做了一个Base64编码,因此肯定不能在其中存放秘密信息,比如说登录密码之类的。

3.Signature是对前面两个部分的签名,防止数据篡改,如果前面两段信息被人修改了发送给服务器端,此时服务器端是可利用签名来验证信息的正确性的。签名需要密钥,密钥是服务器端保存的,用户不知道。算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔,就可以返回给用户。

JWT特点:

1.JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

2.JWT 不加密的情况下,不能将秘密数据写入 JWT。

3.JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

4.JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

5.JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

6.为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

四、OAuth(开放授权)

OAuth(Open Authorization)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容,为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。我们常见的提供OAuth认证服务的厂商有支付宝,QQ,微信。

OAuth协议又有1.0和2.0两个版本。相比较1.0版,2.0版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。

认证流程:

OAuth就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

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

在前后端分离的情境下,我们常使用授权码方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

OAuth2.0四种授权模式:

授权码模式(authorization code)

简化模式(implicit)

密码模式(resource owner password credentials)

客户端模式(client credentials)

OAuth设计理念:

OAuth在”客户端”与”服务提供商”之间,设置一个授权层(authorization layer)。

“客户端”不能直接登录”服务提供商”,只能登录授权层,以此将用户与客户端区分开来。

“客户端”登录授权层所用的令牌(token),与用户的密码不同。用户可在登录时,指定授权层令牌的权限范围和有效期。

“客户端”登录授权层以后,”服务提供商”根据令牌的权限范围和有效期,向”客户端”开放用户储存的资料。


总结

总的来说,具体使用哪种鉴权机制还是需要考虑应用场景。

如果对于安全性要求没有很高的话可以考虑使用HTTP Basic Authentication和session-cookie两种模式。

而对于做前后端分离开发时,需要做接口鉴权的话Token验证比较适合。

做第三方登录时OAuth不失为首选。

赞 (0)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址