Skip to content

接口鉴权的多种情况与解决方案

接口鉴权的多种情况与解决方案

简介

接口鉴权是在进行 API 通信时用于验证请求方身份的重要机制,以确保接口安全性和合法性。在实际应用中,存在多种情况下的接口鉴权需求。

应用场景

当用户需要登录并获得认证后才能访问某些接口,比如用户信息获取、订单提交等操作、第三方应用接入等情况下需要用到鉴权来保护接口数据的安全

常见的鉴权方式:

  • HTTP Basic Authentication鉴权方式这是HTTP协议实现的基本认证方式,我们在浏览网页时,从浏览器正上方弹出的对话框要求我们输入账号密码,正是使用了这种认证方式。

HTTP Basic Authentication鉴权方式的认证过程:

  1. 客户端向服务器请求数据,请求的内容可能是一个网页或者是一个ajax异步请求。此时,假设客户端尚未被验证,则客户端提供如下请求至服务器:

    • Get /index.html HTTP/1.0
    • Host:www.google.com
  2. 服务器向客户端发送验证请求代码401,(WWW-Authenticate: Basic realm=“google.com”,这句话是关键,如果没有,客户端不会弹出用户名和密码输入界面)。

  3. 当符合http1.0或1.1规范的客户端(如IE,FIREFOX)收到401返回值时,将自动弹出一个登录窗口,要求用户输入用户名和密码。

  4. 用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中。

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

常见的鉴权:

  • token鉴权方式
  • session鉴权方式
  • cookie鉴权方式
  • auth2.0

一般来说都是token或者session和cookie,具体用什么可以看自己的文档或者问开发。

token鉴权方式

  1. token鉴权方式流程:

    • 客户端使用账密请求登录
    • 服务端收到请求,验证账密
    • 账密验证通过,服务端生成一个token,再把token发送给客户端
    • 客户端将token存储起来,可以放在cookie或者其他方式如Local Storage 里
    • 以后客户端每次发送请求都需要带上token
    • 服务端收到请求后验证token的合法性,校验通过则返回资源,不通过则返回401状态码(鉴权失败)
  2. token鉴权方式适用场景

    • token验证比较灵活,适用于大部分场景。
    • 常用的token鉴权方式的解决方案是JWT(JSON WEB TOKEN),JWT是通过对带有相关用户信息的
    • JSON进行加密来实现授权验证的方案,加密的方式比较灵活,可以根据需求具体设计。
  1. session+cookie认证流程:

    • 服务器在接受客户端首次访问时在服务器端创建session,然后保存session(我们可以将session保存在内存中,也可以保存在redis中,推荐使用后者),然后给这个session生成一个唯一的标识字符串,然后在响应头中附上这个唯一标识字符串。
    • 签名。这一步只是对sid进行加密处理,服务端会根据这个secret密钥进行解密。(非必需步骤)
    • 浏览器中收到请求响应的时候会解析响应头,然后将sid保存在本地cookie中,浏览器在下次http请求的请求头中会带上该域名下的cookie信息。
    • 服务器在接受客户端请求时会去解析请求头cookie中的sid,然后根据这个sid去找服务器端保存的该客户端的session,然后判断该请求是否合法。
  2. *session+cookie和token的区别

    • session-cookie是通过sessionid来作为浏览器和服务端的链接桥梁,而token验证方式貌似是token来起到sessionid的角色。其实这两者差别是很大的。
  3. 是否含有用户的登录状态:

    • sessionid 只是一个唯一标识的字符串,服务端是根据这个字符串来查询在服务器端保持的session,这里面才保存着用户的登陆状态。
    • 而token本身就是一种登陆成功凭证,他是在登陆成功后根据某种规则生成的一种信息凭证,里面本身就保存着用户的登陆状态。服务器端只需要根据定义的规则校验这个token是否合法就行。
  4. 是否需要cookie(适用客户端的类型有所区别):

    • session-cookie是需要cookie配合的,那么在http代理客户端的选择上就是只有浏览器了,因为只有浏览器才会去解析请求响应头里面的cookie,然后每次请求再默认带上该域名下的cookie。
    • 但是token不一样,是在登陆成功后在请求响应体中返回的信息,客户端在收到响应的时候,可以把它存在本地的cookie/storage/内存中,然后在下一次请求的请求头中带上这个token就行了。所以适用浏览器(即使禁止了cookie),还有原生APP等等。
  5. 时效性:

    • session-cookie的sessionid是在登陆的时候生成的,而且直到登出时一直不变,在一定程度上安全就会低。
    • 而token是可以在一段时间内动态改变的。
  6. 可扩展性:

    • token验证本身是比较灵活的,一是token的解决方案有许多,常用的是JWT。二来我们可以基于token验证机制,专门做一个鉴权服务,用它向多个服务的请求进行统一鉴权。

auth2的流程

  • 向用户请求授权,现在很多的网站在登陆的时候都有第三方登陆的入口,当我们点击等第三方入口时,第三方授权服务会引导我们进入第三方登陆授权页面。
  • 当用户点击授权并登陆后,授权服务器将生成一个用户凭证(code)。
  • 第三方应用后台通过第二步的凭证(code)向授权服务器请求Access Token,即请求授权服务器授权。
  • 授权服务器同意授权后,返回一个资源访问的凭证(Access Token)。
  • 第三方应用通过第四步的凭证(Access Token)向资源服务器请求相关资源。
  • 资源服务器验证凭证(Access Token)通过后,将第三方应用请求的资源返回。

实战演示

Python 演示代码

1)使用 HTTPBasicAuth 类将 HTTP 基本身份验证附加到 Request 对象。

2)通过 auth 参数传递认证数据信息。

import requests
from requests.auth import HTTPBasicAuth

def req():
    url = "https://httpbin.ceshiren.com/basic-auth/ad/123"
    r = requests.get(url = url, auth = HTTPBasicAuth("ad", "123"))
    print(r.json())
    assert r.json()["user"]=='ad'
req()

Java 演示代码

import io.restassured.RestAssured;
import io.restassured.response.Response;

import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class AuthTest {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://httpbin.ceshiren.com";

        Response response = given()
                .auth()
                .basic("ad", "123")
                .when()
                .get("/basic-auth/ad/123")
                .then()
                .statusCode(200)
                .body("authenticated", equalTo(true))
                .body("user", equalTo("ad"))
                .extract()
                .response();

        System.out.println(response.asString());
    }
}

总结

  • 使用 HTTPBasicAuth 解决接口鉴权