字节跳动实习生二面0716

项目中分哪几种用户角色,应该有哪些角色

普通用户和管理员

不同的角色要考虑设置什么权限呢

普通用户:选购商品,查看修改购物车、修改个人资料、密码,支付等。

管理员:上下架商品,找回用户密码,退货

角色、权限怎么设计它们的存储

RBAC角色权限:角色一张表,用户一张表,权限一张表,然后用户-角色、角色-权限分别一张表,表示对应关系。

一个用户对应哪几种角色呢

当时没想到RBAC,用RBAC的话只需要再用户-角色表里添加对应关系即可。

用户发过来请求,怎么判断这个用户是谁

利用JWT的payload识别用户ID

请求头怎么表示用户是谁

微服务传递时在请求头Authorization字段加上用户ID

JWT怎么识别出当前用户是谁

用户信息包含在载荷中
当用户登录或进行身份验证时,服务器会生成一个JWT,并在载荷部分包含用户的唯一标识符(如用户ID)

客户端发送JWT
客户端(如浏览器或移动应用)在随后的请求中,会将JWT作为HTTP请求头(如Authorization: Bearer <token>)或请求体的一部分发送给服务器。

服务器验证JWT
服务器接收到请求后,会首先验证JWT的签名以确保令牌未被篡改。验证通过后,服务器会解析JWT的载荷部分,从中获取用户信息(如user_id),并根据这些信息来识别当前用户。

JWT怎么防止被伪造

强密钥:JWT的签名部分使用密钥(secret)进行加密。确保使用足够长的、复杂的密钥,避免使用弱密钥或默认密钥。

一个用户被盗号了,修改密码,怎么把之前的JWT作废

1. 使用黑名单或白名单机制

策略描述

  • 黑名单
    • 在用户修改密码后,将旧的JWT放入黑名单中,并存储在如Redis这样的内存数据库中。
    • 设置黑名单中JWT的过期时间与原始JWT的过期时间相同,以减少服务器压力。
    • 在每次请求验证JWT时,先检查该JWT是否在黑名单中,如果在则拒绝访问。
  • 白名单
    • 与黑名单相反,只存储有效的JWT在Redis等内存数据库中。
    • 用户修改密码后,移除所有旧JWT的存储,只保留新JWT。
    • 但这种方法需要确保在每次用户认证成功后都更新白名单,且处理逻辑较为复杂。

优点

  • 可以立即作废JWT,防止被恶意使用。
  • 灵活性强,可以根据实际情况选择使用黑名单或白名单。

缺点

  • 需要额外的存储空间和计算资源来维护黑名单或白名单。
  • 增加了系统的复杂性。

2. 结合使用JWT和Refresh Token

策略描述

  • 在用户登录时,不仅颁发一个JWT作为访问令牌,还颁发一个Refresh Token。
  • JWT的过期时间设置得较短(如几分钟到几小时),而Refresh Token的过期时间设置得较长(如几天到几个月)。
  • 当JWT过期时,客户端可以使用Refresh Token向服务器请求一个新的JWT。
  • 在用户修改密码后,使所有之前的Refresh Token失效(可以通过更改用户数据库中的某个字段或状态来实现)。

优点

  • 可以在不影响用户体验的情况下,实现JWT的定期更换和作废。
  • 减少了JWT被盗用的风险。

缺点

  • 需要额外的逻辑来处理Refresh Token的颁发和验证。

3. 更新用户数据库中的状态

策略描述

  • 在用户修改密码时,更新用户数据库中的某个字段(如“最后密码修改时间”)。
  • 在验证JWT时,除了检查JWT的签名和过期时间外,还检查JWT中携带的用户信息与数据库中的信息是否一致(特别是与密码修改时间相关的字段)。

优点

  • 无需额外的存储空间来维护黑名单或白名单。
  • 只需在用户数据库中进行简单的状态更新。

缺点

  • 需要修改JWT的验证逻辑,使其包含对数据库状态的检查。
  • 可能会影响JWT验证的性能。

找当前所在位置周边指定距离内的店铺,怎么实现

Redis的GEO数据结构,当时忘了,一直用数据库

操作系统中程序的内存在它看来是连续的,但是实际上在物理内存上是不连续的,这是怎么实现的。

操作系统中程序的内存在它看来是连续的,但实际上在物理内存上是不连续的,这一特性主要通过虚拟内存技术和内存管理单元(Memory Management Unit, MMU)来实现。以下是具体的实现方式:

1. 虚拟内存技术

虚拟内存是现代操作系统普遍使用的一种技术,它允许程序拥有比实际物理内存更大的地址空间。虚拟内存通过将物理内存和磁盘空间(或其他类型的存储介质)组合起来,为程序提供一个统一的、连续的虚拟地址空间。

  • 地址空间抽象:操作系统为每个运行的程序创建一个独立的地址空间(Address Space),该空间包含了程序的所有相关内存,如代码区、数据区、堆栈区等。这些区域在逻辑上是连续的,但在物理上可能并不连续。
  • 内存映射:操作系统维护一个从虚拟地址到物理地址的映射表(如页表),用于将程序访问的虚拟地址转换为实际的物理地址。当程序访问某个内存地址时,操作系统会查找映射表,找到对应的物理地址,然后访问该物理地址上的数据。

2. 内存管理单元(MMU)

内存管理单元(MMU)是硬件组件,负责处理CPU的内存访问请求,实现虚拟地址到物理地址的转换。

  • 地址转换:当CPU发出内存访问请求时,MMU会拦截该请求,并根据映射表将请求的虚拟地址转换为物理地址。如果映射表中没有相应的条目(即发生了缺页中断),MMU会通知操作系统进行处理(如从磁盘加载相应的页面到物理内存中)。
  • 缓存优化:为了提高地址转换的效率,MMU通常会包含一个翻译后备缓冲器(Translation Lookaside Buffer, TLB),用于缓存最近访问的页表项。当CPU访问某个内存地址时,如果TLB中已有该地址的缓存条目,则可以直接从TLB中获取物理地址,无需再次访问页表。

3. 非连续内存分配的优势

  • 更好的内存利用和管理:非连续内存分配允许程序使用物理内存中的不连续区域,从而减少了内存碎片的产生,提高了内存的利用率。
  • 支持动态加载和动态链接:程序可以在运行时动态地加载和链接库文件,这些库文件可以分布在物理内存中的不同位置,而无需考虑物理内存的连续性。

操作系统的锁有哪些实现

互斥锁、读写锁、自旋锁、乐观锁和悲观锁、可重入锁

所有的KV过期时间相同,所以任何时刻LRU后面节点剩余过期时间比前面节点少,题目要求随意剔除,所以剔除最后一个,还是按照LRU的规则。就是多了个创建时间的属性。

get时用当前时间减去,和过期间隔比一下,看是否过期,过期返回空,否则更新并重置创建时间。

put则和普通LRU一致。

package org.example;

import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.LinkedList;

class LRUCache {
    class Node{
        public int key,val;
        Instant time;
        public Node pre,next;
        Node(){}
    }
    LinkedList<Node> Lru;
    HashMap<Integer,Node> map;
    //当前大小,最大容量,过期时间
    int cnt=0,maxn=0,time_gap;
    Node head,end;
    public LRUCache(int capacity) {
        Lru=new LinkedList<Node>();
        map=new HashMap<Integer,Node>();
        maxn=capacity;
        head=new Node();
        end=new Node();
        head.next=end;
        end.pre=head;
        time_gap=3;
    }

    public int get(int key) {
        Node node=map.get(key);
//        System.out.println(Duration.between(node.time,Instant.now()).getSeconds());
        //不存在或过期
        if(node==null|| Duration.between(node.time,Instant.now()).getSeconds()>time_gap){
            return -1;
        }
        move_to_head(node);
        return node.val;
    }

    public void put(int key, int value) {
        Node node=map.get(key);
        if(node!=null){//更改值
            node.val=value;
            move_to_head(node);
            return;
        }
        if(cnt==maxn){//淘汰
            cnt-=1;
            Node last=end.pre;
            delete(last);
            map.remove(last.key);
        }
        node=new Node();//新增节点
        node.val=value;
        node.key=key;
        node.time=Instant.now();
        map.put(key,node);
        move_to_head(node);//
        cnt+=1;
    }
    void move_to_head(Node node){//移到开头,更新过期时间
        if(node.pre!=null){//
            delete(node);
        }
        Node first=head.next;
        head.next=node;
        node.next=first;
        node.pre=head;
        first.pre=node;
        node.time=Instant.now();
    }
    void delete(Node node){//将节点前后跳过
        Node p=node.pre;
        Node n=node.next;
        p.next=n;
        n.pre=p;
    }

    public static void main(String[] args) throws InterruptedException {
        LRUCache lruCache = new LRUCache(3);
        lruCache.put(1,2);
        lruCache.put(2,3);
        lruCache.put(3,4);
        lruCache.put(4,5);
        System.out.println(lruCache.get(2));
        Thread.sleep(5*1000);
        System.out.println(lruCache.get(1));
        System.out.println(lruCache.get(2));
    }
}

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

装B且挨揍の

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值