前端接口使用restful格式,post与get的区别是什么?

HTTP网络返回的状态码有哪些?

go语言切片与数组的区别是什么?

MySQL实现并发安全避免两个事务同时对一个记录写操作的手段有哪些?

如何实现业务的幂等性(在golang代码中如何避免消息重复或处理已出现的消息重复)?

如何设置redis分布式锁?

SETNX 是 Redis 中的一个命令,全称为 "SET if Not eXists"。它的作用是在键不存在时设置键的值。具体来说,SETNX 的功能如下:
语法
            
            
              plaintext
              
              
            
          
          SETNX key value
        返回值
- 1: 如果键成功设置(即键不存在)。
 - 0: 如果键已经存在,设置失败。
 
用法示例
1. 设置一个键
            
            
              plaintext
              
              
            
          
          SETNX my_key "some_value"
        - 如果 
my_key不存在,则它的值被设置为"some_value",返回 1。 - 如果 
my_key已经存在,则不做任何操作,返回 0。 
2. 用于分布式锁
SETNX 常用于实现分布式锁,因为它可以确保只有一个进程可以获得锁。例如:
            
            
              python
              
              
            
          
          import redis
# 连接到 Redis
client = redis.StrictRedis(host='localhost', port=6379, db=0)
# 尝试获取锁
if client.setnx("my_lock", "some_unique_value"):
    print("Lock acquired")
    # 执行临界区代码
    
    # 释放锁
    client.delete("my_lock")
else:
    print("Lock already acquired")
        注意事项
- 不适合复杂操作 : 
SETNX只能用于简单的键值设置,不能用于复杂的条件判断。 - 锁的有效性 : 在实现分布式锁时,结合使用 
SETNX和设置过期时间可以防止死锁。 

ThreadLocal
ThreadLocal 是 Java 中的一个类,用于提供线程局部变量。每个使用 ThreadLocal 的线程都可以独立地存储和访问自己的变量副本,而不会与其他线程共享。以下是关于 ThreadLocal 的详细解释:
1. 基本概念
- 线程局部变量 : 每个线程在访问 
ThreadLocal变量时,会得到自己独立的副本。这意味着一个线程对ThreadLocal变量的修改不会影响其他线程。 - 存储位置 : 
ThreadLocal变量存储在每个线程的ThreadLocalMap中。 
2. 使用方法
2.1 创建 ThreadLocal 变量
        
            
            
              java
              
              
            
          
          ThreadLocal<String> threadLocalVar = new ThreadLocal<>();
        2.2 设置值
使用 set() 方法将值存储到当前线程的 ThreadLocal 变量中。
            
            
              java
              
              
            
          
          threadLocalVar.set("Hello, ThreadLocal!");
        2.3 获取值
使用 get() 方法从当前线程的 ThreadLocal 变量中获取值。
            
            
              java
              
              
            
          
          String value = threadLocalVar.get(); // 返回 "Hello, ThreadLocal!"
        2.4 清除值
使用 remove() 方法可以清除当前线程的 ThreadLocal 变量值。
            
            
              java
              
              
            
          
          threadLocalVar.remove();
        3. 示例代码
以下是一个使用 ThreadLocal 的简单示例:
            
            
              java
              
              
            
          
          public class ThreadLocalExample {
    private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0);
    public static void main(String[] args) {
        Runnable task = () -> {
            Integer value = threadLocalValue.get();
            value++;
            threadLocalValue.set(value);
            System.out.println(Thread.currentThread().getName() + ": " + threadLocalValue.get());
        };
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);
        thread1.start();
        thread2.start();
    }
}
        4. 适用场景
- 用户会话信息 : 在 Web 应用中,可以使用 
ThreadLocal存储每个请求的用户信息。 - 数据库连接: 每个线程可以持有自己的数据库连接,避免共享连接导致的线程安全问题。
 - 性能优化: 减少对象的创建和销毁,避免频繁的上下文传递。
 
5. 注意事项
- 内存泄漏 : 如果不调用 
remove()方法,线程局部变量可能会导致内存泄漏,尤其在使用线程池时。 - 不适合跨线程使用 : 
ThreadLocal变量仅在创建它的线程中可见,其他线程无法访问。 - 调试困难 : 使用 
ThreadLocal可能会让调试变得复杂,因为变量的状态依赖于线程的生命周期。 
总结
ThreadLocal 是一个强大的工具,适用于需要线程隔离的数据存储场景。合理使用可以提高性能和简化代码,但也需要注意内存管理和线程安全问题。
超卖问题怎么解决?
- redis使用lua脚本判断和扣减库存
 - 使用redis队列避免数据不一致的问题(先将数据存入redis队列中,从redis队列中取出记录添加到数据库)
 
后端如何对一个请求鉴权?为什么JWT要双签发?被截获了怎么办?如果人为地想要禁止某个用户的访问应该怎么做?
一、后端请求鉴权流程
后端通常通过以下步骤验证请求合法性:
- Token 提取
从请求头(如Authorization: Bearer <token>)或 Cookie 中获取 JWT。 - 签名验证
用预设密钥验证 JWT 签名是否被篡改(例如使用 HMAC 或 RSA 算法)。 - 有效期检查
校验exp(过期时间)和nbf(生效时间)字段。 - 业务逻辑鉴权
- 从 JWT 解析用户角色/权限(如 
role: admin)。 - 对比请求资源所需的权限(如 RBAC 模型)。
 
 - 从 JWT 解析用户角色/权限(如 
 - 敏感操作二次验证
关键操作(如支付)要求重新输入密码或 2FA 验证。 
            
            
              python
              
              
            
          
          # Python 伪代码示例(使用 PyJWT)
def verify_request(request):
    token = request.headers.get("Authorization").split("Bearer ")[1]
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        if payload["role"] != "admin":
            raise PermissionError("无权访问")
        return True
    except jwt.ExpiredSignatureError:
        raise Unauthorized("Token过期")
        二、JWT 双签发机制及作用
双签发(Dual-Issuer) 指同时使用两个密钥签发 Token:
- 主密钥(Primary Key)
- 用于签发长期有效的 访问令牌(Access Token)(如有效期 1 小时)。
 
 - 从密钥(Secondary Key)
- 用于签发短期有效的 刷新令牌(Refresh Token)(如有效期 7 天)。
 
 
✔ 核心目的:安全性隔离
- 访问令牌泄露风险高:频繁在网络传输,暴露概率大。
 - 刷新令牌严格保护:仅用于获取新访问令牌,存储于安全环境(如 HttpOnly Cookie)。
 - 攻击窗口最小化:即使 Access Token 被截获,有效期短且无法直接获取新 Token。
 
三、JWT 被截获的应对措施
| 攻击类型 | 防御方案 | 示例 | 
|---|---|---|
| 中间人窃听 | 强制 HTTPS + HSTS 头 | 服务器配置 TLS 1.3 | 
| 客户端脚本窃取 | HttpOnly Cookie 存储 + XSS 防护 | 设置 Set-Cookie: HttpOnly; Secure | 
| Token 泄露 | 短期有效期 + 刷新令牌轮转 | Access Token 有效期 ≤15 分钟 | 
| 重放攻击 | JTI(JWT ID)唯一标识 + 服务端黑名单 | 使用 Redis 记录已使用的 JTI | 
刷新令牌轮转示例 :
每次用 Refresh Token 获取新 Access Token 时,同步生成新 Refresh Token 并作废旧令牌。这样即使旧刷新令牌被截获,攻击者只能使用一次。
四、禁止特定用户访问的解决方案
1. 短期封禁:令牌黑名单(Token Blacklist)
- 适用场景:立即踢出已登录用户。
 - 实现方式 :
- 用户注销或封禁时,将 JWT 的 
jti(唯一ID)加入 Redis 黑名单。 - 鉴权时校验 
jti是否在黑名单中。 
 - 用户注销或封禁时,将 JWT 的 
 - 优点:实时生效。
 - 缺点:增加数据库查询开销。
 
            
            
              python
              
              
            
          
          # 封禁用户时
redis.set(f"blacklist:{jti}", "1", ex=ACCESS_TOKEN_EXPIRE)
# 鉴权时检查
if redis.exists(f"blacklist:{jti}"):
    raise Forbidden("用户已被封禁")
        2. 长期封禁:用户状态标记
- 适用场景:永久禁止访问。
 - 实现方式 :
- 在用户数据库添加 
is_active字段。 - 鉴权时查询用户状态(注意缓存用户信息避免频繁查库)。
 
 - 在用户数据库添加 
 - 优点:一劳永逸。
 - 缺点:状态变更后需等待 Token 自然过期。
 
3. 强制令牌失效:刷新令牌回收
- 封禁用户时,删除该用户的刷新令牌。
 - 用户 Access Token 过期后无法续签,自动退出。
 
五、最佳实践总结
- 双签发必要性
✅ 隔离高风险令牌(Access Token)与高价值令牌(Refresh Token)。 - 防截获组合拳
✅ HTTPS + 短有效期 + HttpOnly Cookie + 刷新令牌轮转。 - 封禁用户策略
- 紧急场景:令牌黑名单(实时生效)。
 - 永久封禁:标记用户状态 + 回收刷新令牌。
 
 - 性能优化
- 黑名单用 Redis 存储并设置自动过期(与 Token 有效期对齐)。
 - 用户状态变化时清理缓存(如 Redis 中的用户信息)。
 
 
关键原则 :JWT 本身无状态,需通过黑名单/用户状态引入必要状态控制,在安全性和性能间取得平衡。



