解决前端不支持cookie造成的跨域问题

174 阅读2分钟

解决前端不支持cookie的造成的跨域问题

image.png

原因: 后端默认DefaultWebSessionManager它只接受Cookie中存储的JsessionId. 查询发现在redis中不存在对应的key.

如何解决:

image.png

简单来说就是后端获取session的方式发生改变,改为获取前端的请求头信息,解决前端不支持cookie的问题。

后端只需要重写DefaultWebSessionManager中getSessionId()的方法。并且客户发送请求时,在请求头中携带sessionId即可,

1.将sessionId放入请求头。

1.1修改后端登录成功的方法,将sessionId返回给前端

image.png

image.png

1.2修改前端登录成功的方法,将sessionId存到localStorage中

image.png

//将后端传过来的sessionId存到token中  
localStorage.setItem("token",result.data.data)

1.3修改main.js文件

在main.js中配置axios请求拦截器,他的执行在axios请求发送之前,所以在第一次登陆的时候会获取sessionId并且存储到token中

image.png

//设置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配置类

image.png

4.修改shiroFilter过滤器

我们发现跨域请求,会发送两个请求:第一个OPTIONS请求,第二个请求是真实的请求。

OPTIONS请求:先头部队。

所以我们对OPTIONS请求都要放行。

image.png

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);
    }
}