文章目录
在项目开发中,使用了session保存邮箱验证的验证码,当使用swagger测试时没有问题,但是vue项目中测试的时候,明明验证码都发送成功了,也填写了发送过来的验证码,却返回“验证码未发送”。
这是验证验证码的代码,返回“验证码未发送”,则可以知道,该浏览器在服务器的session为null,即传过来的sessionid为空,因为服务器要根据请求cookie中的sessionid找服务器中对应的session。可是,vue在发送验证码请求中,就已经在response中为浏览器设置了一个sessionid放在cookie中,为什么再次发送请求,请求中的sessionid为null呢?
//验证验证码
public R judgeCode(@PathVariable("code") String code, @RequestBody User user, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return R.error().message("验证码未发送");
}
String code1 = (String) session.getAttribute(user.getId());
if (code1.equals(code)) {
user.setPassword(MD5.encrypt(user.getPassword()));
userService.saveOrUpdate(user);
session.invalidate(); //修改完后,删除该session
return R.ok().message("验证通过,成功修改密码");
}
return R.error().message("验证码错误,请重新输入");
}
原来是因为大部分请求库,比如ajax,axios等,发送跨域请求时,默认设置都是:withCredentials: false,这个设置的意思就是请求头中不携带cookie等,所以服务器一直收到的sessionid为null。
解决办法:
前端和后端都要设置!
前端:
在axios请求中设置withCredentials: true。
后端:
设置allowCredentials也为true。
以springboot为例,添加一个CorsFilter跨域过滤器,主要是config.setAllowCredentials(true);这一行起作用,表示允许请求头携带cookie。
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.setAllowCredentials(true); //主要是这一行
config.addAllowedMethod("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
这样就解决了。
关于session:
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 —— 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,springboot通过request.getSession(boolean create)设置是否新建),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id。
总的来说,客户端第一次需要使用session时,服务器就第一次创建一个session,并通过本次响应返回这个session的session id给客户端,作为这个客户端对应session的唯一凭证。session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串。
保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。