后台跨域造成session失效
1.场景还原
最近在笔者在springboot中集成token机制发现了一个隐藏bug:“后台实现跨域,前端运用ajax请求后台接口成功回调;一切看似那么顺利,其实不然,session已经后台失效了,每次请求的sessionId不一致,之前缓存在session中的值取出来都为null,怎么回事?瞬间懵逼”,很多人可能问什么跨域?百度哈,不赘述!
2.寻求症结
①后台实现跨域
@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController extends BaseController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
UserService userService;
@Autowired
LoginService loginService;
@GetMapping(value = "/login")
public Map<String,Object> getLogin(String loginName,String password){
String zhangxing = Token.genetateToken();
session.setAttribute("zhangxing",zhangxing);
boolean login = false;
//储存token
String pwd = loginService.getPassword(loginName);
Map<String,Object> map = new HashMap<String, Object>();
if(pwd.equals(password)){
login = true;
}
map.put("login",login);
map.put("token",zhangxing);
return map;
}}
没错,后台就凭
@CrossOrigin
一个注解解决了跨域问题。
String zhangxing = Token.genetateToken();
session.setAttribute("zhangxing",zhangxing);
登录并将随机生成的token缓存到session中
②前端ajax请求后台接口
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>token</title>
<!-- 引入 echarts.js -->
<script type="text/javascript" src="js/jQuery.js"></script>
<script type="text/javascript" src="js/cache.js"></script>
</head>
<body>
用户名:<input type="text" id="username"><br><br>
密 码:<input type="text" id="pwd"><br>
<button onclick="getlogin()">登录</button>
<!-- xhrFields:{withCredentials:true}, -->
<script type="text/javascript">
function getlogin(){
alert($("#username").val());
alert($("#pwd").val());
$.ajax({
type: "get",
url: "http://localhost:8089/user/login",
data:{
"loginName":$("#username").val(),
"password":$("#pwd").val()
},
beforeSend: function(XMLHttpRequest){
// alert(pkinds[0]);
},
//请求成功回调
success: function(data, textStatus){
alert("进来了");
alert(data.login);
alert(data.token);
if(data.login){
localStorage.setItem("token",data.token);
window.location.href ="good.html";
}
},
complete: function(XMLHttpRequest, textStatus){
},
error: function(){
alert("请求网络失败!。。。。。。");
}
});
}
</script>
</body>
</html>
前端登录成功后得到后台的token,并缓存在localStorage中
localStorage.setItem("token",data.token);
并且跳转到另一个界面
window.location.href ="good.html";③good.html前端代码
<html>
<head>
<meta charset="utf-8">
<title>File upload</title>
<script type="text/javascript" src="js/jQuery.js"></script>
<script type="text/javascript" src="js/cache.js"></script>
</head>
<body onload="getAlert()">
<!-- // action="fileupload"对应web.xml中<servlet-mapping>中<url-pattern>的设置. -->
<img src="img/feng.jpg" alt="">
<script>
function getAlert(){
var token=localStorage.getItem("token");
alert(token)
$.ajax({
type: "get",
url: "http://localhost:8089/user/getcheck",
data:{
"tokenStr":token
},
/* xhrFields:{withCredentials:true},*/
beforeSend: function(XMLHttpRequest){
// alert(pkinds[0]);
},
//请求成功回调
success: function(data, textStatus){
alert("进来了");
alert(data.check);
if(data.check){
window.location.href ="new.html";
localStorage.removeItem("token");
}else{
window.location.href ="login.html";
}
},
complete: function(XMLHttpRequest, textStatus){
},
error: function(){
window.location.href ="login.html";
alert("请求网络失败!。。。。。。");
}
});
}
</script>
</body>
</html>
问题来了?这步前端取出缓存在localStorage的token值
var token=localStorage.getItem("token");
然后把取出的token传到后台校验接口,代码如下:
@GetMapping(value = "/getcheck")
public Map<String,Object> getCheck(String tokenStr){
String token = (String) session.getAttribute("zhangxing");
boolean check =false;
//取出token
System.out.println("取出来的值:"+token);
if(token != null){
if(token.equals(tokenStr)){
check = true;
}
}
Map<String,Object> map = new HashMap<String, Object>();
map.put("check",check);
return map;
}
这时发现,无论你怎么挣扎,后台取出session的缓存值始终为null
debug之后发现两个controller中的sessionId居然不一致,一脸懵逼!
洗个脸再来,经过逐级排除,笔者定位应该是ajax请求后台跨域接口使session失效,经过一番试错,这个定位果真准!
3.解决方案
只需在ajax中加一个参数设置 xhrFields:{withCredentials:true},完整ajax代码
$.ajax({
type: "get",
url: "http://localhost:8089/user/login",
data:{
"loginName":$("#username").val(),
"password":$("#pwd").val()
},
xhrFields:{withCredentials:true},
beforeSend: function(XMLHttpRequest){
// alert(pkinds[0]);
},
//请求成功回调
success: function(data, textStatus){
alert("进来了");
alert(data.login);
alert(data.token);
if(data.login){
localStorage.setItem("token",data.token);
window.location.href ="good.html";
}
},
complete: function(XMLHttpRequest, textStatus){
},
error: function(){
alert("请求网络失败!。。。。。。");
}
});
不用质疑,就是这么简单!
效果图:
好了,这个问题就over了,我是张星,欢迎加入博主技术讨论群,群号:313145288
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 跨域访问会导致session失效
- 下一篇: iframe跨域Session丢失问题的解决办法
