前后端分离,SpringBoot拦截器中,获取的请求头token为NULL问题解决

本文探讨了在前后端分离中遇到的跨域问题,重点在于设置跨域并允许携带Cookie后,后端拦截器无法获取请求头参数的问题。原因是浏览器在发送实际请求前会先发送OPTIONS预检请求。解决方案是在后端拦截器中对OPTIONS请求进行特殊处理,直接放行,以确保后续的GET/POST等请求能够被正确处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景:

在做前后端分离时,牵扯到跨域,但是已经设置了跨域

前端设置了允许携带Cookie
axios.defaults.withCredentials = true;

后端也配置了跨域:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    	//项目中的所有接口都支持跨域
    	registry.addMapping("/**")
    	//所有地址都可以访问,也可以配置具体地址
    	.allowedOrigins("*")
    	//允许的请求方式
    	.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
    	//是否支持跨域Cookie
    	.allowCredentials(true)
    	// 跨域允许时间
    	.maxAge(3600);
    }
}

浏览器端查看发送的请求,请求头中包含 Authorization
在这里插入图片描述
但是在后端拦截器中获取的参数总是为 null
在这里插入图片描述
在这里插入图片描述

二、原因:

实际上发送了两次请求,第一次为 OPTIONS 请求,第二次才 GET/POST… 请求
在OPTIONS请求中,不会携带请求头的参数,所以在拦截器上获取请求头为空,自定义的拦截器拦截成功
第一次请求不能通过,就不能获取第二次的请求了 GET/POST…
第一次请求不带参数,第二次请求才带参数

三、解决:

在拦截器中,如果请求为 OPTIONS 请求,则返回 true,表示可以正常访问,然后就会收到真正的 GET/POST 请求

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
    System.out.println("OPTIONS请求,放行");
    return true;
}
好的,下面是一个简单的Spring Boot前后端分离登录拦截器的例子: 首先,我们需要创建一个拦截器类来检查用户是否已登录: ```java public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token == null) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } // 校验token,如果token无效,则返回401状态码 if (!validateToken(token)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } return true; } private boolean validateToken(String token) { // TODO: 实现token验证逻辑 return true; } } ``` 在上面的代码中,我们实现了`HandlerInterceptor`接口,并覆盖了其中的`preHandle()`方法,在该方法中,我们从请求头获取token,如果token为空,则返回401状态码。否则,我们实现了`validateToken()`方法来校验token是否有效,如果无效,则返回401状态码。 接下来,我们需要在Spring Boot应用程序中注册拦截器。可以通过在配置类中添加`@Configuration`注解来实现: ```java @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**"); } } ``` 在上面的代码中,我们首先使用`@Autowired`注解注入了我们之前定义的`LoginInterceptor`对象,然后通过`addInterceptors()`方法注册了拦截器,并指定了需要拦截的路径。 最后,我们还需要在`Controller`中添加`@RequestMapping`注解来指定处理登录请求的方法: ```java @RestController @RequestMapping("/api") public class LoginController { @PostMapping("/login") public String login(@RequestBody Map<String, String> params) { String username = params.get("username"); String password = params.get("password"); // 校验用户名和密码,并生成token,将token返回给前端 String token = generateToken(username); return token; } private String generateToken(String username) { // TODO: 实现token生成逻辑 return "abcd1234"; } } ``` 在上面的代码中,我们首先使用`@PostMapping`注解指定了处理登录请求的方法,该方法会校验用户名和密码,并生成token,将token返回给前端。 需要注意的是,由于是前后端分离的架构,因此我们在登录请求中使用了`@RequestBody`注解和`Map<String, String>`类型的参数来接收前端传递的参数。同时,我们在返回值中直接返回了token,而不是渲染视图。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值