微头条项目开发笔记|CORS跨域统一配置 + 用户注册完整登录认证功能迭代

微头条项目开发笔记|CORS跨域统一配置 + 用户注册完整登录认证功能迭代

一、课次32:全局CORS跨域统一配置(彻底解决前后端跨域报错)

1. 开发痛点回顾

之前联调时前端5173访问后端8080会触发浏览器CORS跨域拦截,临时方案是给每个Controller加@CrossOrigin注解,代码冗余、维护麻烦,本节课采用全局MVC配置统一处理跨域,一次性放行前端域名,无需在每个控制器重复写注解。

2. 后端核心配置改造

修改InterceptorConfig拦截器配置类,新增addCorsMappings重写方法统一配置跨域规则:

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .allowedOrigins("http://localhost:5173") // 允许前端开发域名
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 放行全部请求方式
            .allowedHeaders("*") // 允许所有请求头(包含Authorization携带Token)
            .allowCredentials(true); // 允许携带Cookie、Token凭证
}

配置说明:

  • /**:匹配后端全部接口路径;
  • OPTIONS请求必须放行,浏览器预检请求依赖该配置;
  • 配置完成删除所有Controller上零散的@CrossOrigin注解,避免配置冲突。

3. 前端配套代理确认与修改

  1. vite.config.js 本地代理(开发环境核心)
export default defineConfig({
  plugins: [vue()],
  server: {
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080', // 后端真实地址
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '') // 自动剔除/api前缀转发给后端
      }
    }
  }
})
  1. axios请求基础地址同步修改
    request.jsbaseURL改为/api,前端所有接口请求自动携带/api前缀,由vite代理转发到后端8080端口,彻底规避浏览器跨域限制。

4. 测试验证流程

  1. 删除Controller临时@CrossOrigin注解;
  2. 重启SpringBoot后端;
  3. 重启Vue前端项目;
  4. 打开登录页输入账号密码,无跨域报错、正常跳转首页,代表跨域配置生效。

二、课次33:用户注册功能 + 完整登录认证闭环(前端路由守卫+axios拦截器)

开发目标

  1. 后端新增注册接口,校验用户名唯一性,完成用户入库;
  2. 前端新增注册页面逻辑,注册成功自动跳转登录页;
  3. 封装axios全局请求/响应拦截器,自动携带Token、捕获401未登录;
  4. 配置前端路由守卫,未登录用户禁止访问首页、新闻发布等需要鉴权页面。

后端开发流程

  1. 新建注册接收DTO UserRegisterDTO
package com.weitoutiao.dto;
import lombok.Data;
@Data
public class UserRegisterDTO {
    private String username;
    private String password;
}
  1. 扩展UserService接口,新增注册抽象方法
boolean register(String username, String password);
  1. UserServiceImpl实现注册逻辑
  • 先通过MyBatis-Plus查询数据库,判断用户名是否重复;
  • 用户名不存在则新建用户对象,默认角色为普通user、新闻发布数量初始0;
  • 暂未做密码加密,后续可拓展MD5加密逻辑。
@Override
public boolean register(String username, String password) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(User::getUsername, username);
    if (this.getOne(wrapper) != null) {
        return false;
    }
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);
    user.setRole("user");
    user.setNewsCount(0);
    return this.save(user);
}
  1. UserController新增注册接口
@PostMapping("/register")
public Result<?> register(@RequestBody UserRegisterDTO dto) {
    boolean success = userService.register(dto.getUsername(), dto.getPassword());
    if (success) {
        return Result.success("注册成功");
    } else {
        return Result.error("用户名已存在");
    }
}

前端全套配套改造

  1. 封装axios拦截器(request.js)
  • 请求拦截器:每次发送请求自动从本地存储读取Token,挂载到请求头Authorization
  • 响应拦截器:捕获后端401未登录状态码,清空本地Token、用户名,强制跳转到登录页,解决Token过期后页面无响应问题。
import axios from 'axios'
const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})
// 请求拦截:自动携带token
request.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})
// 响应拦截:统一处理401失效
request.interceptors.response.use(
  response => response.data,
  error => {
    if (error.response?.status === 401) {
      localStorage.removeItem('token')
      localStorage.removeItem('username')
      window.location.href = '/login'
    }
    return Promise.reject(error)
  }
)
export default request
  1. 接口封装user.js新增注册请求
export const register = (data) => {
  return request.post('/user/register', data)
}
  1. 注册页面Register.vue编写提交逻辑
    表单校验通过后调用注册接口,根据后端返回code判断结果:注册成功弹窗提示并跳转登录页,用户名重复/网络异常弹出对应错误提示。
const handleRegister = async () => {
  if (!formRef.value) return
  await formRef.value.validate(async (valid) => {
    if (valid) {
      try {
        const res = await register({ username: form.username, password: form.password })
        if (res.code === 200) {
          ElMessage.success('注册成功,请登录')
          router.push('/login')
        } else {
          ElMessage.error(res.message || '注册失败')
        }
      } catch {
        ElMessage.error('请求失败,请检查网络')
      }
    }
  })
}

项目完成状态总结

  1. 后端:/user/login登录、/user/register注册双接口完成,登录下发JWT令牌,注册校验用户名重复;
  2. 前端功能闭环:
    • 注册页面:提交表单→后端校验→成功跳转登录;
    • 登录页面:账号密码登录→存储token到本地→跳转首页;
    • 全局请求自动携带Token,Token失效自动退回登录页;
    • 路由守卫限制未登录用户访问受保护页面,刷新页面登录状态持久化;
  3. 跨域问题彻底根治,无需额外注解,开发环境前后端正常互通。

今日整体复盘

  1. 解决长期遗留的跨域痛点,学会Spring MVC全局CORS配置,区分开发环境前端代理与后端跨域两种协同方案;
  2. 完善用户模块完整业务链路:注册-登录-鉴权-登录失效拦截,搭建标准前后端分离认证体系;
  3. 掌握axios拦截器、前端本地存储、路由守卫三大前端鉴权核心工具,实现无状态JWT认证全流程;
  4. 待优化方向:后端密码加密存储、封装全局统一异常码、线上环境跨域域名适配、前端路由守卫代码补充完善。

SpringBoot结构:
image
image

VS:
image

posted @ 2026-06-18 16:05  橙糯CiiiiiX  阅读(14)  评论(0)    收藏  举报