Spring Boot中基于学生域名的CORS跨域Token接口配置问题
动态配置CORS规则实现学生域名匹配
嗨,这个需求我之前处理过类似的,静态的@CrossOrigin(origins = "*")肯定满足不了这种按学生对应域名动态放行的要求,咱们得用动态CORS过滤器来实现,下面是具体的步骤和代码示例:
第一步:移除静态CORS注解
先把控制器上的@CrossOrigin(origins = "*")删掉,因为咱们要通过过滤器动态处理CORS规则,静态注解会和动态配置冲突。修改后的控制器接口:
@RequestMapping(value = "/getToken") public String provideToken() { return "tokenvalue"; }
第二步:实现动态CORS过滤器
咱们自定义一个继承OncePerRequestFilter的过滤器,在请求进来时:
- 提取请求参数里的
username和password - 从
student表查询该学生对应的domain - 根据查询结果设置CORS响应头,匹配则放行,不匹配则拒绝请求
1. 数据库查询逻辑(以MyBatis为例)
先写一个Mapper接口,用来根据用户名和密码查询对应域名:
@Mapper public interface StudentMapper { @Select("SELECT domain FROM student WHERE name = #{username} AND password = #{password}") String getDomainByUsernameAndPassword(@Param("username") String username, @Param("password") String password); }
2. 自定义动态CORS过滤器
@Component public class DynamicCorsFilter extends OncePerRequestFilter { @Autowired private StudentMapper studentMapper; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 提取请求参数中的用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); String allowedDomain = null; // 校验参数非空后查询数据库 if (username != null && !username.isEmpty() && password != null && !password.isEmpty()) { allowedDomain = studentMapper.getDomainByUsernameAndPassword(username, password); } // 处理CORS规则 if (allowedDomain != null) { // 设置允许的跨域源(必须和请求的Origin完全匹配,数据库要存完整协议+域名,比如https://something.com) response.setHeader("Access-Control-Allow-Origin", allowedDomain); // 允许的请求方法 response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); // 允许的请求头 response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); // 是否允许携带凭证(比如Cookie) response.setHeader("Access-Control-Allow-Credentials", "true"); } else { // 没有匹配到对应域名,直接返回403拒绝请求 response.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } // 处理浏览器的OPTIONS预检请求(跨域非简单请求会先发送OPTIONS) if ("OPTIONS".equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); return; } // 继续执行后续请求链 filterChain.doFilter(request, response); } }
关键注意事项
- 域名存储规范:数据库里的
domain字段必须存完整的协议+域名(比如https://something.com),因为浏览器发送的Origin头是带协议的,必须完全匹配才会生效。 - 性能优化:可以给查询结果加缓存(比如Redis或Guava Cache),避免每次请求都查数据库,尤其是用户量较大的场景。
- 参数校验:一定要对
username和password做非空校验,防止空参数导致的数据库查询异常。 - 预检请求处理:必须正确响应OPTIONS请求,否则浏览器会拦截后续的实际请求。
内容的提问来源于stack exchange,提问作者lambad
相关产品推荐
相关产品推荐

