day05---登录认证

22 阅读2分钟

核心问题:

没登录也能访问系统 → 不安全
目标:登录成功发 token;后续请求必须带 token;后端统一拦截校验 token


1)登录接口(/login)

做什么

  • 本质就是查询select * from emp where username=? and password=?
  • 成功返回:id/username/name/token

关键实现

  • LoginControllerPOST /login@RequestBody Emp
  • EmpService.login():查到员工 → 生成 JWT → 返回 LoginInfo
  • EmpMapper:按 username+password 查询

✅ 复习口诀:查库成功 → 生成JWT → 返回给前端存 localStorage


2)为什么需要登录校验(HTTP 无状态)

  • HTTP 每次请求独立,后端不知道你之前是否登录

  • 所以要做:

    1. 登录成功后“存一个标记” (token)
    2. 后续请求统一拦截校验(Filter/Interceptor)

3)会话跟踪三种方案(记优缺点就行)

Cookie(客户端)

  • 自动携带,但:不安全 / 可禁用 / 不能跨域 / 移动端不友好

Session(服务端,底层还是 Cookie)

  • 相对安全,但:集群下会话不共享(请求打到不同服务器就丢)

Token(主流)

  • 登录成功返回 token,后续请求带 token(请求头)
  • 跨端、跨域、支持集群、服务器压力小
  • 缺点:需要自己实现生成/校验

✅ 面试回答:企业里基本用 Token/JWT


4)JWT(你必须掌握的点)

JWT是什么

  • Header.Payload.Signature
  • Payload 可放自定义数据(id/username)
  • Signature 防篡改
  • 过期时间 exp

两个关键动作

  • 生成:JwtUtils.generateJwt(claims)

  • 解析校验:JwtUtils.parseJWT(token)

    • 解析报错 = 被篡改/过期/非法

✅ 口诀:密钥一致才解析得过;任意改一位就失败;过期也失败


5)登录成功下发 token(项目落地)

  • login 成功后:

    • claims.put("id", ...)
    • claims.put("username", ...)
    • token = JwtUtils.generateJwt(claims)
    • 返回给前端
  • 前端存:localStorage

  • 后续请求:请求头携带 token


6)统一拦截校验(两选一:Filter 或 Interceptor)

A. Filter(Servlet 层,拦截所有资源)

实现步骤:

  1. 获取 URL
  2. 如果是 /login → 放行
  3. 取 header:token
  4. token 为空 → 401
  5. token 解析失败 → 401
  6. 放行:chain.doFilter()

特点:

  • 拦截范围更大(所有资源)
  • 配置:@WebFilter("/*") + @ServletComponentScan

B. Interceptor(Spring 层,只拦 Controller)

实现逻辑一样,写在 preHandle

  • 返回 true 放行,false 拦截
  • WebMvcConfigurer#addInterceptors 注册
  • 可用 excludePathPatterns("/login") 更优雅(不用自己判断 url.contains)

✅ 实战建议:用 Interceptor 更常见更顺手(只管 Controller)


预期效果

  • 没登录访问任意业务接口 → 401 → 前端跳登录页
  • 登录成功拿到 token → 后续请求都带 token → 正常访问

3 个练习小目标(按顺序)

  1. 登录成功能返回 token(Apifox 能看到 token)
  2. 浏览器 localStorage 存 token,请求头自动带 token
  3. 拦截器/过滤器能挡住“没 token / token 过期 / token 被篡改”的请求(401)