V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Eyon
V2EX  ›  问与答

没搞懂 HTTP 请求的安全验证,求指导!

  •  
  •   Eyon · 2022-06-02 17:02:24 +08:00 · 4346 次点击
    这是一个创建于 898 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如请求 https://abc.com/api ,服务器那边可能需要一个验证,比如要求 headers.Authorization === "abcdefg",

    那么,也就是说我在请求是,必须在 headers 中添加 Authorization = 'abcdefg'就可以成功请求,这个逻辑没错吧?

    问题是:

    比如自己做个网站,浏览器打开首页,就需要从服务器提供的 API 中获取一些数据以供后续服务,API 那边定义是要求 headers.Authorization === 'abcdefg',所以前端写 axios 请求的时候,就加上了 authorization="abcdefg"这个请求,正常工作没有问题。可是,由于在浏览器中的请求标头中可以看到 Authorization:abcdefg 这个明文信息,任何人都可以看到,那不就是任何人都可以通过其他任何方式(比如 postman)来请求这个数据了吗?

    当然,你可能会说加密。即便吧 abcdefg 加密成任何形式的密钥,但始终能在请求标头中看到加密后的密钥,用这个密钥发送请求依然可以成功,意义何在呢?

    当然,这个问题一定是我自己哪里逻辑没搞清楚。求解答!

    81 条回复    2022-06-04 06:30:53 +08:00
    virusdefender
        1
    virusdefender  
       2022-06-02 17:04:12 +08:00
    你自己再写一个后端,来中转这个请求
    Eyon
        2
    Eyon  
    OP
       2022-06-02 17:06:38 +08:00
    @virusdefender 还是没搞懂逻辑,中转的意义又何在呢?任何人不是一样可以通过 postman 带上这个 Authorization 来请求数据吗?
    polaa
        3
    polaa  
       2022-06-02 17:10:09 +08:00 via iPhone
    啥叫任何人 …. mitm 原理了解一下
    dcty
        4
    dcty  
       2022-06-02 17:14:24 +08:00
    如果你是 HTTPS ,header 就是加密的,只有你本地才能看到的,不存在任何人都可以看到,除非 mitm 。
    gkirito
        5
    gkirito  
       2022-06-02 17:15:35 +08:00
    建议看看 OAuth 等类似认证逻辑,一般你能拿到这个 Authorization 后面的 token 是要先进行正常的账号密码登录,才能获获取到这个 token ,而且这个 token 是带签名和过期,即便你在使用过程中,一不小心被别人窃取了这个 token ,也是可以直接取消这个 token ,出现这个 Authorization 是为了简化登录认证过程,只需要第一次登录,服务端下发一个带签名可过期 token 这个 token 的获取,是要用户登录成功后端才返回,并且前端要保证返回 token 使用过程中不会乱发到别的网站
    dcty
        6
    dcty  
       2022-06-02 17:19:03 +08:00   ❤️ 1
    其实,OP 的意思应该是不想自己的 API 能够被爬虫或者第三方客户端直接利用了吧。
    不提供网页版,客户端做 SSL Pinning 。
    Eyon
        7
    Eyon  
    OP
       2022-06-02 17:19:18 +08:00
    https://imgur.com/a/IK7fIOh

    比如这个,这个不是就可以看到吗?
    然后拿着这个 authorization 不是就可以去请求这个接口中的数据吗?
    cheng6563
        8
    cheng6563  
       2022-06-02 17:21:25 +08:00
    就是设计如此,HTTPS 防网络连接攻击,但不防用户自己从浏览器拷贝 Token 。

    你看百度网盘的第三方 cli 客户端,就是要用户手动从已登录的浏览器里面扣 cookie 使用。

    有一些混淆,HASH 之类的方法可以进一步保护 Token ,但不是常规方案。
    IvanLi127
        9
    IvanLi127  
       2022-06-02 17:21:42 +08:00
    大概可以类比为,你如果把口令说出去了,大家都知道了。在你把口令泄露出去之前,这个口令有意义吗?
    cheneydog
        10
    cheneydog  
       2022-06-02 17:22:04 +08:00
    只有客户端和服务端能看到吧,中间人看不到的。
    中间人要想看到这个值,就得在创建 https 链接阶段开始攻击。
    Eyon
        11
    Eyon  
    OP
       2022-06-02 17:22:05 +08:00
    @gkirito 没有设计用户系统,所以我就不知道这个东西的意义在哪里。
    FanError
        12
    FanError  
       2022-06-02 17:23:02 +08:00
    @Eyon 你自己看到,不代表别人能看到呀,就好比,我现在想知道你的 authorization ,我去哪里看,跑到你电脑上面来看吗?
    ryd994
        13
    ryd994  
       2022-06-02 17:23:08 +08:00 via Android
    1. 如果你想挡住非浏览器用户,你应该用反爬技术 /图灵测试。鉴权的目的是确认请求来源掌握这个密码。而不是确认请求来源是特定真人。
    2. HTTP basic/digest authentication 一般配合 HTTPS 使用。脱离 HTTPS/CA 的鉴权很容易被中间人。
    3. “即便吧 abcdefg 加密成任何形式的密钥,但始终能在请求标头中看到加密后的密钥,用这个密钥发送请求依然可以成功”
    这就是我反对用户侧密码 hash 代替 HTTPS 的原因。用户侧密码 hash 只不过是把 hash 结果变成了实质上的密码。
    4. 你这个需求,一般通过限时 /限次数的 token 控制。网页中嵌入 token 。API 请求时带上 token 。就算有人能从网页源码中找到 token ,token 也会过期被服务器拒绝。
    Eyon
        14
    Eyon  
    OP
       2022-06-02 17:25:30 +08:00
    @cheneydog 关键是客户端的用户也有可能拿着我这个“abcdefg”去用 postman 请求啊,因为他浏览器能看到。

    这个帖子没有讨论中间人攻击什么的。
    Eyon
        15
    Eyon  
    OP
       2022-06-02 17:27:15 +08:00
    @ryd994 我不过是想挡住浏览器用户而已。也就是说用户请求我的页面,页面可以获取这一份数据。但是如果他拿到 postman 中,就不能获取我这个数据。
    Eyon
        16
    Eyon  
    OP
       2022-06-02 17:31:04 +08:00
    @ryd994 通过限时限次,在网页中嵌入 token 的流程是一个什么样的流程呢?

    我目前是想当然的认为:

    所有的用户打开浏览器首页,都发送 auth:abcdefg ,服务器端判断确实有 auth:abcdefg 这个字段,就放行数据。也就是:

    在 index.html 的 js 中写死‘abcdefg’这个 auth————————>服务器端接收,给数据。

    当然,这个流程一定是不对的,应该是一个什么样的流程呢?
    huxins
        17
    huxins  
       2022-06-02 17:34:40 +08:00
    楼主解决问题的方向错了,防止使用者通过非浏览器方式调用,可以动态生成 sign 等。但也只是加大破解难度,做不到完全禁止。
    攻和防,只是成本问题。
    你只要想在浏览器中展现数据,用户就一定可以在其他地方(如 postman )中,获取数据。
    常用解决方案:5 秒盾,各种验证码。
    cctrv
        18
    cctrv  
       2022-06-02 17:39:31 +08:00
    1. 想拒絕用戶從 PostMan 之類的工具取得數據,是不存在的方案。
    2. 要認識清楚任何客戶端模式( Web 、App )都無法保證數據只有一種方式獲得。
    3. 如果你真的那麼想保護你的數據,那麼只有一條路給你,開發對應的硬件,獨立的網絡通道,讓外人無法從任何方式監視到你的數據流動,那麼才可以保護你的數據。
    Eyon
        19
    Eyon  
    OP
       2022-06-02 17:39:53 +08:00
    @huxins 比如,我做个图书网站,里面有 10000 本书。
    在浏览器中,我用 get_books_list 这个请求,得到这 10000 本书的 array ,然后在浏览器中展现出来供用户浏览。

    但是,用户也可以直接在 postman 中,用上他在浏览器中看到的 auth token ,直接在 postman 中请求 get_books_list 这个接口,得到我这 10000 本书的 json 数据,包括价格、图片、isbn 等等,这不是很尴尬吗?

    难道,本来就是这样的?
    leo108
        20
    leo108  
       2022-06-02 17:42:01 +08:00
    太长不看版:

    楼主:我想把一个钉子钉进墙里,但是🪛根本就没法做到,那🪛存在的意义是啥?

    因为你要实现的功能就不是 Authorization header 设计出来要解决的问题。

    当然楼主的需求也有解决方案,在🪛上焊一个🔨的头就可以了:token 变成动态的,一个 token 只能被使用一次,而生成 token 的逻辑需要进行各种加密混淆以提高破解的成本。缺点也很明显,🪛柄太细,容易断(任何在客户端实现的逻辑都是可以被破解的)
    Eyon
        21
    Eyon  
    OP
       2022-06-02 17:42:33 +08:00
    @huxins 那么,你是不是可以非常非常非常非常轻松的获取到 V2EX 的帖子列表 JSON 数据?
    Eyon
        22
    Eyon  
    OP
       2022-06-02 17:43:45 +08:00
    @leo108 比如我服务器要求 token=abcdefg ,但是怎么让客户端知道我服务器要求 token=abcdefg ,让它能够用这个 abcdefg 来请求数据呢?
    iyear
        23
    iyear  
       2022-06-02 17:45:40 +08:00
    @Eyon #19 用户电脑上的浏览器发请求和 postman 发请求本质就是一样的啊,最终都是调 socket 发起 TCP 连接。极端一点的比喻,你的服务器能判断用户电脑用的水电还是核电吗
    iyear
        24
    iyear  
       2022-06-02 17:46:41 +08:00
    你的方向应该在反爬虫上,而不是鉴权机制上
    Eyon
        25
    Eyon  
    OP
       2022-06-02 17:47:36 +08:00
    @iyear 那么,你是不是可以非常非常非常非常轻松的获取到 V2EX 的帖子列表 JSON 数据?
    foolnius
        26
    foolnius  
       2022-06-02 17:48:09 +08:00
    Authorization 是拿来鉴权的,不是给你反 postman 的
    如果你不想要用户拿这个 Authorization 就可以任意请求接口,要加其他辅助手段,来保证你这个请求参数用了一次就不能再用第二次。比方说浏览器 Web 端加一个混淆过代码的生成签名函数,每次请求对参数特征进行签名,服务端校验签名合法性就好了。当然,不存在绝对安全,只是提高逆向签名函数过程的难度而已,简单的如楼上所说加验证码也行,根据接口数据的重要性,权衡消耗资源,针对选择不同的方法就好。
    FanError
        27
    FanError  
       2022-06-02 17:48:11 +08:00
    看半天楼主原来想要的是反爬,且只能让用户在浏览器中访问。
    huxins
        28
    huxins  
       2022-06-02 17:48:28 +08:00
    @Eyon 本就如此,权限只是限制特定用户(比如:张三),而不是特定用户的特定方式(比如:张三的 Postman )
    iyear
        29
    iyear  
       2022-06-02 17:48:38 +08:00
    @Eyon #25 一大堆 V2EX 的第三方客户端,有些官方不提供的 api 不都是抓包抓下来的吗
    foolnius
        30
    foolnius  
       2022-06-02 17:52:51 +08:00
    @Eyon #19
    “比如,我做个图书网站,里面有 10000 本书。”
    你觉得这 10000 本书数据重要吗?如果你觉得重要,你就可以上很高级别的反爬虫策略。
    @Eyon #25
    “是不是可以非常非常非常非常轻松的获取到 V2EX 的帖子列表 JSON 数据?”
    本来就是很轻松获取的啊,站长甚至提供了 API 文档 /help/api
    你要理解数据的重要程度,有没有必要让你花费资源(客户端资源、服务器资源)去做这些反爬虫策略
    Eyon
        31
    Eyon  
    OP
       2022-06-02 17:54:23 +08:00
    @iyear 我的意思不是抓包那么复杂。

    而是,用户既然看得到这个 Authorization: Basic xxxxxxxx 这一串,可以直接在 Postman 中请求得到 json 格式的帖子列表,而用不着抓包,这个不是很尴尬吗?
    iyear
        32
    iyear  
       2022-06-02 17:56:44 +08:00
    @Eyon #31 你要看到 Au 这一行不就是抓包吗? f12 就是浏览器抓包呀。。就是这么轻松简单
    Pastsong
        33
    Pastsong  
       2022-06-02 17:58:41 +08:00
    @Eyon 你刚刚描述了抓包的过程....
    你要真的你的前端代码是明文跑在用户机器上的,用户想怎么跑就能怎么跑,你客户端能拿到的数据用户也能用其他方式拿到。想反抓包反爬有别的手段,和 HTTP 无关
    Eyon
        34
    Eyon  
    OP
       2022-06-02 18:01:58 +08:00
    @iyear
    @Pastsong

    为什么我看 V2EX 的请求头中没有 Authorization 这一行,看不到这一行是不是代表站长一定没有用 Authorization 这个参数来鉴权获取本帖的评论列表?
    iyear
        35
    iyear  
       2022-06-02 18:04:11 +08:00 via Android
    @Eyon 那也可以用 cookie 呀。。具体放什么头里自己定的嘛
    otakustay
        36
    otakustay  
       2022-06-02 18:04:29 +08:00
    @Eyon #14 这属于权限管理,他当然可以拿着去用,就算你改成 cookie 他也能拿着 cookie 去用。他 postman 发的请求也代表他的操作,有权限的自然让他成功,没权限的自然要拦下来,并没有什么特别
    blackeeper
        38
    blackeeper  
       2022-06-02 18:13:45 +08:00
    我猜楼主应该是写前端的。
    请求一个接口 https://abc.com/api ,需要做一个简单的认证,那么最简单的办法是只要有人 headers 中添加 Authorization = xx 或者 yy ,就可以表示这个是谁,并且认证通过后是一个合法请求。
    那么不管你是用浏览器,还是用 postman 只要带了正确的 Authorization 头部那么这就是一个合法请求,跟用什么客户端没有任何关系。
    另,https 协议别人是看不到请求的 url ,header 和 body ,只能看到域名 abc.com 。所以不存在其他人能看到一说,只有你自己看见
    crab
        39
    crab  
       2022-06-02 18:18:23 +08:00
    Authorization 带上时间戳签名
    Akitora
        40
    Akitora  
       2022-06-02 18:22:16 +08:00 via Android
    只要这个数据是给人看的,绝对的反爬就是不存在的
    只是成本问题+1
    libook
        41
    libook  
       2022-06-02 18:29:35 +08:00
    这个流程大体是这样的:
    1. 用户在登录页面登录;
    2. 服务器验证用户账号信息,登录成功则将用户会话信息(如用户 ID )+当前时间合并起来进行加密,加密成一个密文字符串,然后放到返回 Header 的 Authorization 中,返回给用户浏览器;
    3. 登录成功的页面从服务器返回的 Authorization 头中提取这个信息,并存在 WebStorage 中;
    4. 用户访问其他登录后才能访问的页面时,页面从浏览器的 WebStorage 中读取上述字符串,以请求 Authorization 头的值随请求发到服务器;
    5. 服务器从请求 Authorization 头提取字符串,进行解密,获得用户会话信息和上一次生成 Authorization 的时间;用户会话信息用来确定是哪个用户,复杂权限系统可以以此判断用户是否有权访问当前资源;时间用来验证距离上次生成这个密文多长时间,比如超过了半个小时,那么可以认定这个 Authorization 过期;如果 Authorization 有效则用用户会话信息+当前最新时间再次生成 Authorization ,放在返回头中返回给用户。
    6. 回到第 4 步循环。

    可以了解一下 JWT 。
    Z5460520
        42
    Z5460520  
       2022-06-02 18:30:32 +08:00
    @Eyon 之前我也很困惑这种 jwt 的验证。其实你可以去了解一下跨域请求攻击,做这个 Authorization=“abcd”,是防止钓鱼网站利用 session 的机制对 api 进行请求。加了这个口令之后,至少你可以允许使用这个口令的用户请求后端地址。至于你不想他直接获取你所有的信息,你可以使用一些特定的字段去限制他获取的信息的长度,有 100 本书,我不会一次返回给他,而是通过特定的其他字段才能获取所有的数据。
    libook
        43
    libook  
       2022-06-02 18:32:21 +08:00
    安全都是相对的,确保安全的一个最低限度的条件就是物理隔离,比如你的电脑是安全的,那么你只需要确保从你电脑发出的信息都是加密的,除了服务器以外的其他人不能看到解密的原文,你的信息就是安全的。

    HTTPS 使用了 TLS 加密,所保障的就是这种“点对点加密”。

    换言之,如果你的电脑已经被各种病毒木马侵占,你的所有请求信息在加密前就被人看光光,就没法确保安全。
    libook
        44
    libook  
       2022-06-02 18:35:46 +08:00
    @libook #41 应该是回到第 3 步
    bjfane
        45
    bjfane  
       2022-06-02 19:20:31 +08:00
    哈哈哈,和我的一个需求一样, 太多了 没看其他大神的解决方案,https 是肯定要的,在这个基础之上
    ch2
        46
    ch2  
       2022-06-02 19:23:57 +08:00
    @Eyon #15 你想要的是 api 签名机制,但是这个东西也是不可能完全避免 hacker 直接把你的签名机制拿过来用。就跟灰产的猫鼠游戏永远玩的下去一样,你永远无法保证所有的请求都是自己的客户端发过来的
    bjfane
        47
    bjfane  
       2022-06-02 19:24:32 +08:00
    没打完发出去了,再来一条吧,
    比如:我的 4 个接口,1 不鉴权 但有参数 ,
    2 3 4 鉴权,凭证是 1 的参数输入正确了,给返回的内容 cache 起来就行了

    第二个方案是 1 2 3 4 鉴权 凭证是访问第一个页面自己输入的,只有正确所有接口才能返回数据。
    yeqizhang
        48
    yeqizhang  
       2022-06-02 20:00:04 +08:00 via Android
    我以前也和楼主一样的疑问。

    而现在,我对等保测评,要求 https 下传输手机号也要求加密感到困惑
    yeqizhang
        49
    yeqizhang  
       2022-06-02 20:07:01 +08:00 via Android
    有一个技术叫浏览器指纹,自己专门做个 sdk ,不知道能否解决楼主不想让人 postman 请求的问题
    bavtoex
        50
    bavtoex  
       2022-06-02 20:45:16 +08:00
    @iyear 哈哈!帮楼主解释的清清楚楚,赞!
    thunderw
        51
    thunderw  
       2022-06-02 21:22:58 +08:00
    HTTP 的这个 Authorization 本来就是相当于客户输入的密码,为啥你要纠结如何让用户不知道这个密码?不太理解纠结的点在哪里。你可能主要还是误会了 Authorization 的用意。

    既然敞开门来做生意,用户想用 IE 用 IE ,想用 Postman 用 Postman ,想用 curl 用 curl 呀……
    AItsuki
        52
    AItsuki  
       2022-06-03 04:24:22 +08:00
    你是不是想错了什么……
    1. 如果是使用 HTTPS ,别人是看不到的。
    2. 你说别人能看到不会是别人使用你电脑的浏览器进开发者模式看吧…… 都用上你电脑了,那你哪些没退出的账号别人不是随便用。。。
    psydonki
        53
    psydonki  
       2022-06-03 05:52:28 +08:00
    OP 你是对的,确实不应该将后台服务的 token 直接暴露给浏览器。
    感觉你们团队也在摸索前后端分离和微服务...


    你可能有点混淆了 Authorization 和 long term token;

    拿 jwt 最佳实践来说,Authorization 中应该传登录行为产生的 access_token ( jwt ),一般过期时限为 15~60 分钟;具体步骤参见 @libook 41 楼。

    long term token 一般是用在 Server to Server 通信时的简单校验; 如下图中 gateway 和 Service 之间。


    所以一般微服务框架中会存在一个 API gateway 的角色,用来向前端返回和校验 jwt ;
    同时充当反向代理,与后台服务进行交互,如果后台服务也是暴露在公网的情况下,出于安全考虑就会用到 long term token;


    一图胜千言,


    当然在实际的项目中,还是根据自己的需要,可以选择对应的云服务或者自己简单实现一个;
    我自己 Next.js 项目中的样例:

    ```
    // src/pages/api/v1/[...param].js
    import axios from 'axios';

    export default async (req, res) => {
    const instance = axios.create({
    baseURL: process.env.LC_API_BASE_URL,
    headers: {
    'token': process.env.LC_API_TOKEN,
    'Content-Type': 'application/json',
    }
    });

    try {
    var response;

    if (req.method === "GET") {
    response = await instance.get(req.url);
    }
    else if (req.method === "POST") {
    response = await instance.post(req.url, req.body);
    }
    else if (req.method === "PUT") {
    response = await instance.put(req.url, req.body);
    }
    res.status(200).json(response.data)
    } catch (err) {
    var response = err.response;
    res.status(response.status).json(response.data);
    }
    }

    ```
    binux
        54
    binux  
       2022-06-03 06:58:36 +08:00 via Android
    安全不来源于破解工具简单,会的人多不多。
    byte10
        55
    byte10  
       2022-06-03 09:21:37 +08:00   ❤️ 1
    @yeqizhang 主要是逻辑没搞明白,用现实的东西举例子就可以了、
    @gkirito 跟 oauth 没关系,基本逻辑都没搞明白

    V2EX 也会经常出现这样的问题,主要还是很基本很基本很基本的东西,没搞明白。之前有公司一个同事也问道,如何保证 cookie 的安全,比如把淘宝的 cookie 从我的电脑拷贝下来,放到他电脑上去,岂不是一样的可以访问我的淘宝。但是问题是: 你怎么能拷贝我的电脑浏览器的 cookie 呢?我的电脑锁屏是有加密的,如果我允许你使用我的电脑,那么就有可能存在的这样的问题。。就好像你没法防止你小孩偷你抽屉的零食,因为他可以进卧室,客厅,但是你可以知道零食被偷的最有可能就是那么几个人。

    https 是加密的请求,head 也看不到,所以中间人是没办法看到的,所以一般是安全的。你说的任何人是指谁?你身边的同事吗?朋友吗?如果你都允许他使用的你电脑,那么你是很难防止他使用你的浏览器的,除非你把电脑的浏览器 APP 单独加密使用。如果是一台公共的电脑,那么就只有每次访问过后进行退出登录,或者每次访问都需要密码。为啥经常会有小白陷入这么困境,思维太混乱了,太容易被绕进去了。我见过太多的这样的情况了,每次我都很头疼,解释不清楚的。。。之前的公司也遇到过这样的人。

    记住没有任何人可以看到你的 Authorization ,除非你自己泄露出去,就好比所有的人如果知道你的银行卡密码,只要拿到你的银行卡就可以取钱,你自己都不保管好?去投诉银行卡不安全是吗?现实多少这样的人?

    类似的案例,别人都告诉你了,不要去河里游泳,不要给陌生人验证码,多少餐桌鸡就是这样被坑死的。

    另外安全是在一定的范围内的,你很难防止你的亲人偷的你密码转你的钱,你在睡觉的时候,在洗澡的时候,在任何时候,都有可能被亲人转走钱。但是你可以防止别人,陌生人转走你的钱,这是最基本的逻辑。

    不知道解释清楚没,能帮 一个算一个。
    byte10
        56
    byte10  
       2022-06-03 09:31:09 +08:00   ❤️ 1
    对于: “而是,用户既然看得到这个 Authorization: Basic xxxxxxxx 这一串,可以直接在 Postman 中请求得到 json 格式的帖子列表,而用不着抓包,这个不是很尴尬吗?”

    你这个想法非常的危险,我作为用户,我可以用谷歌浏览器,我可以用我自己开发的浏览器,我可以用 httpclient ,可以用 postman ,你为啥要阻拦我?你凭什么阻拦我的?我自己的数据我想怎么访问就怎么访问。既然是公共的数据,我想怎么访问就怎么访问,我用鼠标去点击翻页也可以,用脚本自动点击翻页也可以,你为啥要管我?

    如果你想要阻拦我,就只能允许这个网页内容只能在你的 app 中访问,你可以把业务都写在你的 app 中,加入各种限制和检测。另外告诉你的是:app 大多都是 http 请求,也是可以被逆向找到访问的 token ,然后我还是可以用 postman 进行访问,你为啥那么想不开?要限制我的访问方式?

    头大。。。你翻不过来了,思维太容易固化了,这个问题解决之后,也会有下一个问题。目前我没有啥方案,多画图试试看,多画点流程图,应该能提升逻辑思维能力。
    byte10
        57
    byte10  
       2022-06-03 09:40:48 +08:00
    @bjfane 需求有问题,存粹添加麻烦,自找麻烦,增加了一些校验而已。postman 也可以先请求第 1 个接口,再请求第 2,3,4 的接口呢?头大。
    @blackeeper https 的话,域名貌似也看不到吧?只看到 tcp 中的 ip ,域名应该是在 http 协议头的 host 上
    @psydonki 还对。。。又来一个。好家伙,那么多人没明白。
    conver
        58
    conver  
       2022-06-03 10:40:30 +08:00 via iPhone
    楼主担心的是重放攻击吧,做 api 签名可以解决,时间戳+uuid+签名,过期或者 uuid 重复就拒绝
    montaro2017
        59
    montaro2017  
       2022-06-03 10:40:31 +08:00 via Android
    如果要反爬,建议套个 cf
    disk
        60
    disk  
       2022-06-03 11:02:34 +08:00 via iPhone
    @yeqizhang 提高破解成本,想搞一样可以给你伪造指纹
    DOLLOR
        61
    DOLLOR  
       2022-06-03 11:14:00 +08:00
    一句话:
    Authorization 是用来识别你是谁的,不是用来拦截你是怎么进来的,不在乎你用的是浏览器、postman 、curl 。
    aliveyang
        62
    aliveyang  
       2022-06-03 11:46:56 +08:00
    你的 Authorization 怎么就任何人都可以看到呢?在你身后看?
    psydonki
        63
    psydonki  
       2022-06-03 12:08:09 +08:00
    @byte10 估计你没看懂我的回答...

    图片在这个帖子加不上了,可以查看我回复历史,最近的那个图片;


    对于普通用户而言,获得自己的短期 access_token 没有问题;当然也可以 copy 出来通过 postman 请求后端的资源;
    比如像这样的 header ,Authorization: Bearer {{jwt}}


    OP 这样实现的问题在于同时暴露了后端服务的地址和长期 /固定 token ;
    最明显的隐患在于,假设用户 A 获取自己信息的 url:
    https://api.abc.com/users/12345
    headers:
    Authorization: Basic {{base64 encoded username:password}}

    假设 12345 是用户 id, 我完全可以猜测 id 就是一个递增序列,通过 postman 去请求其他人的信息;
    https://api.abc.com/users/12346
    headers:
    Authorization: Basic {{base64 encoded username:password}}

    @Eyon 不确定解释清楚了没有,如果你们团队的架构是微服务的话,你可以 Google 一下 azure api gateway.
    byte10
        64
    byte10  
       2022-06-03 13:20:39 +08:00
    @psydonki 你用自己的 token ,去请求别的用户数据,这个是横向越权。。这个是漏洞、业务设计的漏洞。
    janus77
        65
    janus77  
       2022-06-03 14:08:50 +08:00
    大哥,Authorization 就跟钥匙一样,你不把钥匙给别人他就没法用 postman 拿到跟你一样的数据
    每个人的钥匙不同,所以每个人获取的数据也不一定相同,比如已登录和未登录,登录 A 和登录 B 等等。
    “为什么 V2EX 可以随便看”因为很多内容站长没有做区分。当然也有一些内容站长做了区分,比如你能看到我的消息提醒吗?你要拿到我的 Authorization 才能看到我的消息提醒,但是你怎么拿到呢?我会给你吗?
    “某些请求没有这个 Authorization 是不是就代表没有这个功能”当然不是,也有其他的方式,只不过 Authorization 是一种比较流行的方式。
    另外,Authorization 是可以设置有效期的,后台发现有问题可以随时令他失效,这样就算你拿到了我的 Authorization ,一旦被我发现,我会换一个用,你手里这个也就废了
    wdssmq
        66
    wdssmq  
       2022-06-03 14:35:30 +08:00
    《爱宠大机密》里,那只兔子用萝卜啃了把钥匙打开了笼子,每次涉及相关讨论时我都会想到这个;

    动画肯定是不现实的:

    1 、萝卜的硬度不够; 2 、要和真钥匙形状一样;

    现实中解决了这两个问题可以说它就是把真钥匙;
    ji39
        67
    ji39  
       2022-06-03 15:25:15 +08:00
    浏览器打开首页就要加额外的请求头,难以理解
    blackeeper
        68
    blackeeper  
       2022-06-03 15:31:38 +08:00
    @byte10 你抓一下包就知道了,TLS 层 hello 包握手的时候可以看到域名,这也是 GWF 拦截域名最主要的点
    Kinnice
        69
    Kinnice  
       2022-06-03 16:59:24 +08:00 via Android
    @Eyon 是的,就是非常非常的轻松就可以获取到。
    Kinnice
        70
    Kinnice  
       2022-06-03 17:06:01 +08:00 via Android
    1. http headers 内的鉴权,无论是 Authorization 还是 Cookie ,都是可以被用户轻易拿到,并且在 postman 等工具内复现
    2. https 保证了中间人(即运营商等)不会获取到你的这些参数
    3. 你想让用户只能在浏览器内获取结果,其他工具内不可以,这是不存在的,但是可以通过
    3.1 加密返回内容(对返回的 json 进行加密),然后使用 js 进行解密后展示,提高对抗难度。
    3.2 动态修改你的鉴权参数例如携带请求时间,如果过了指定范围即不返回。
    3.3 .....
    qwqaq
        71
    qwqaq  
       2022-06-03 17:15:31 +08:00
    参考《 HTTP 权威指南》第 13 章 摘要认证:

    基本认证便捷灵活,但极不安全。用户名和密码都是以明文形式传送的,也没有采取任何措施防止对报文的篡改。安全使用基本认证的唯一方式就是将其与 SSL 配合使用。

    摘要认证与基本认证兼容,但却更为安全。

    摘要认证是另一种 HTTP 认证协议,它试图修复基本认证协议的严重缺陷。具体来说,摘要认证进行了如下改进:

    - 永远不会以明文方式在网络上发送密码。
    - 可以防止而已用户捕获并重放认证的握手过程。
    - 可以有选择地防止对报文内容的篡改。
    - 防范其他几种常见的攻击方式。
    qwqaq
        72
    qwqaq  
       2022-06-03 17:18:07 +08:00
    @qwqaq *可以防止恶意用户捕获并重放认证的握手过程。
    coolzjy
        73
    coolzjy  
       2022-06-03 17:35:14 +08:00
    OP 的问题应该是我给你钥匙只想让你开锁进门,但是不妨碍别人拿到了这把钥匙也能开锁。

    基于其他人无法很容易的拿到钥匙这一假设,我们一般认为通过这把钥匙进门的人就是你。但在进行一些风险等级比较高的操作时(比如删除账户,或涉及资金等),通常需要其他认证因素辅助来确定你就是你(比如支付宝的登陆密码 /支付密码)。

    至于 OP 后面补充的图书馆的例子,那就属于防止接口恶意使用的问题了,这个跟钥匙 /锁就没什么关系了。
    timpaik
        74
    timpaik  
       2022-06-03 18:09:26 +08:00 via Android
    如果楼主想要保护的其实是自己应用在 api 平台是私钥的话,请搞一个后端作鉴权和限流。楼主很明显问了一个 X-Y 问题。。。
    byte10
        75
    byte10  
       2022-06-03 18:10:08 +08:00
    @coolzjy 是的,很简单的逻辑。
    @blackeeper soga, 谢谢指正
    aecra1
        76
    aecra1  
       2022-06-03 18:19:08 +08:00 via Android
    信任是有边界的
    chnwillliu
        77
    chnwillliu  
       2022-06-03 19:12:33 +08:00 via Android
    @Eyon

    “用户既然看得到这个 Authorization: Basic xxxxxxxx 这一串,可以直接在 Postman 中请求得到 json 格式的帖子列表,而用不着抓包,这个不是很尴尬吗?”

    一点也不尴尬啊。浏览器又叫 user agent, 本来 user agent 就可以有很多种形式,postman 是,你代码里的 http client 也是,甚至命令行的 curl ,他们都是 user agent 。http 又不是设计来只给浏览器用的。
    chnwillliu
        78
    chnwillliu  
       2022-06-03 19:20:52 +08:00 via Android
    Http 协议只是提供了一种建议的鉴权方式,它方便你的服务端去鉴别 user agent 发起的这次请求是否符合某些身份要求。在 Http 协议的概念里是没有浏览器这种东西的,只有 user agent, 或者说 http client 端。
    xiangyuecn
        79
    xiangyuecn  
       2022-06-03 19:37:18 +08:00
    简单点讲,就是:滥用
    chnwillliu
        80
    chnwillliu  
       2022-06-03 19:53:34 +08:00 via Android
    @Eyon

    "没有设计用户系统,所以我就不知道这个东西的意义在哪里。"

    这就是问题所在啊。不同系统对鉴权的要求不一样。

    你开了家图书馆,读者进来只要到服务台领一张通行证跑到入口处,保安一看通行证,上写天王盖地虎,就让你进了。这就是你在用的认证。下次你知道口令了,自己弄了张一样的纸写上天王盖地虎,保安照样让你进。

    你觉得这样不对是吗,那是因为你的图书馆不应该用这种最简单的方式呀。

    HTTP authorisation 并没有限制你只能用天王盖地虎这种对口号的方式鉴权。你可以有用户系统,鉴定用户名密码,每次报用户名密码太烦了,那可以鉴定一次然后发临时通行证。没有用户系统还要对任意用户提供服务,那要哪门子 authorisation 。
    mxT52CRuqR6o5
        81
    mxT52CRuqR6o5  
       2022-06-04 06:30:53 +08:00 via Android
    为了防止被盗用一般都会时服务器转发的,让使用方自行解决老用盗用问题(比如这个时候我可以设计一个人机交互验证码),如果设计成可以直接客户端可以直接请求非转发的那种一般都会检查来源,会设置个白名单(但还是会有给非 web 端使用盗用风险)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1361 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:54 · PVG 01:54 · LAX 09:54 · JFK 12:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.