解决前端不支持cookie的造成的跨域问题
原因: 后端默认DefaultWebSessionManager它只接受Cookie中存储的JsessionId. 查询发现在redis中不存在对应的key.
如何解决:
简单来说就是后端获取session的方式发生改变,改为获取前端的请求头信息,解决前端不支持cookie的问题。
后端只需要重写DefaultWebSessionManager中getSessionId()的方法。并且客户发送请求时,在请求头中携带sessionId即可,
1.将sessionId放入请求头。
1.1修改后端登录成功的方法,将sessionId返回给前端
1.2修改前端登录成功的方法,将sessionId存到localStorage中
//将后端传过来的sessionId存到token中
localStorage.setItem("token",result.data.data)
1.3修改main.js文件
在main.js中配置axios请求拦截器,他的执行在axios请求发送之前,所以在第一次登陆的时候会获取sessionId并且存储到token中
//设置axios的请求拦截器
axios.interceptors.request.use(config=>{
//从localStorage中获取token的值
var item = localStorage.getItem("token")
if(item){
config.headers.token=item;
}
return config;
})
2.重写DefaultWebSessionManager的方法
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
public class MyWebSessionManager extends DefaultWebSessionManager {
private static final String AUTHORIZATION = "token";
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//获取请求头中名称为token的内容
String id = WebUtils.toHttp(request).getHeader("token");
if (!StringUtils.isEmpty(id)) { //如果存在该token
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "Stateless request");
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
} else {
//从cookie中获取sessionId.
return super.getSessionId(request, response);
}
}
}
3.修改shiro配置类
4.修改shiroFilter过滤器
我们发现跨域请求,会发送两个请求:第一个OPTIONS请求,第二个请求是真实的请求。
OPTIONS请求:先头部队。
所以我们对OPTIONS请求都要放行。
public class LoginFilter extends FormAuthenticationFilter {
//未登录访问资源时,会触发该方法。 ---默认内容是重定向到登录页面--重写改为返回json数据
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//解决响应数据的中文乱码问题
response.setContentType("application/json;charset=utf-8");
//获取用于向客户端发送文本数据的对象
final PrintWriter writer = response.getWriter();
final Result result = new Result(401,"未登录",null);
//把java对象转为json字符串
final String string = JSON.toJSONString(result);
writer.write(string);
//刷新流
writer.flush();
//关流
writer.close();
return false;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
HttpServletRequest request1 = (HttpServletRequest) request;
//获取请求方式
final String method = request1.getMethod();
if("OPTIONS".equals(method)){
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
}