接口鉴权的多种情况与解决方案
接口鉴权的多种情况与解决方案
简介
接口鉴权是在进行 API 通信时用于验证请求方身份的重要机制,以确保接口安全性和合法性。在实际应用中,存在多种情况下的接口鉴权需求。
应用场景
当用户需要登录并获得认证后才能访问某些接口,比如用户信息获取、订单提交等操作、第三方应用接入等情况下需要用到鉴权来保护接口数据的安全
常见的鉴权方式:
- HTTP Basic Authentication鉴权方式这是HTTP协议实现的基本认证方式,我们在浏览网页时,从浏览器正上方弹出的对话框要求我们输入账号密码,正是使用了这种认证方式。
HTTP Basic Authentication鉴权方式的认证过程:
-
客户端向服务器请求数据,请求的内容可能是一个网页或者是一个ajax异步请求。此时,假设客户端尚未被验证,则客户端提供如下请求至服务器:
- Get /index.html HTTP/1.0
- Host:www.google.com
-
服务器向客户端发送验证请求代码401,(WWW-Authenticate: Basic realm=“google.com”,这句话是关键,如果没有,客户端不会弹出用户名和密码输入界面)。
-
当符合http1.0或1.1规范的客户端(如IE,FIREFOX)收到401返回值时,将自动弹出一个登录窗口,要求用户输入用户名和密码。
-
用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中。
-
服务器收到上述请求信息后,将Authorization字段后的用户信息取出、解密,将解密后的用户名及密码与用户数据库进行比较验证,如用户名及密码正确,服务器则根据请求,将所请求资源发送给客户端。
常见的鉴权:
- token鉴权方式
- session鉴权方式
- cookie鉴权方式
- auth2.0
一般来说都是token或者session和cookie,具体用什么可以看自己的文档或者问开发。
token鉴权方式
-
token鉴权方式流程:
- 客户端使用账密请求登录
- 服务端收到请求,验证账密
- 账密验证通过,服务端生成一个token,再把token发送给客户端
- 客户端将token存储起来,可以放在cookie或者其他方式如Local Storage 里
- 以后客户端每次发送请求都需要带上token
- 服务端收到请求后验证token的合法性,校验通过则返回资源,不通过则返回401状态码(鉴权失败)
-
token鉴权方式适用场景
- token验证比较灵活,适用于大部分场景。
- 常用的token鉴权方式的解决方案是JWT(JSON WEB TOKEN),JWT是通过对带有相关用户信息的
- JSON进行加密来实现授权验证的方案,加密的方式比较灵活,可以根据需求具体设计。
session + cookie鉴权方式
-
session+cookie认证流程:
- 服务器在接受客户端首次访问时在服务器端创建session,然后保存session(我们可以将session保存在内存中,也可以保存在redis中,推荐使用后者),然后给这个session生成一个唯一的标识字符串,然后在响应头中附上这个唯一标识字符串。
- 签名。这一步只是对sid进行加密处理,服务端会根据这个secret密钥进行解密。(非必需步骤)
- 浏览器中收到请求响应的时候会解析响应头,然后将sid保存在本地cookie中,浏览器在下次http请求的请求头中会带上该域名下的cookie信息。
- 服务器在接受客户端请求时会去解析请求头cookie中的sid,然后根据这个sid去找服务器端保存的该客户端的session,然后判断该请求是否合法。
-
*session+cookie和token的区别
- session-cookie是通过sessionid来作为浏览器和服务端的链接桥梁,而token验证方式貌似是token来起到sessionid的角色。其实这两者差别是很大的。
-
是否含有用户的登录状态:
- sessionid 只是一个唯一标识的字符串,服务端是根据这个字符串来查询在服务器端保持的session,这里面才保存着用户的登陆状态。
- 而token本身就是一种登陆成功凭证,他是在登陆成功后根据某种规则生成的一种信息凭证,里面本身就保存着用户的登陆状态。服务器端只需要根据定义的规则校验这个token是否合法就行。
-
是否需要cookie(适用客户端的类型有所区别):
- session-cookie是需要cookie配合的,那么在http代理客户端的选择上就是只有浏览器了,因为只有浏览器才会去解析请求响应头里面的cookie,然后每次请求再默认带上该域名下的cookie。
- 但是token不一样,是在登陆成功后在请求响应体中返回的信息,客户端在收到响应的时候,可以把它存在本地的cookie/storage/内存中,然后在下一次请求的请求头中带上这个token就行了。所以适用浏览器(即使禁止了cookie),还有原生APP等等。
-
时效性:
- session-cookie的sessionid是在登陆的时候生成的,而且直到登出时一直不变,在一定程度上安全就会低。
- 而token是可以在一段时间内动态改变的。
-
可扩展性:
- 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 解决接口鉴权