Vue学习使用心得(四):对vue-admin-template轮子学习的心得体会(下)

前后端交互

跨域问题

产生

浏览器的同源策略,同源策略是一个安全策略,用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

同源

scheme://host.domain:port/path/filename
  • scheme - 定义因特网服务的类型(http、https、ftp、file)
  • host - 定义域主机(http的默认主机是www)
  • domain - 定义因特网域名(比如baidu.com)
  • :port - 定义主机上的端口号(http默认端口号是80)
  • path - 定义服务器上的路径
  • filename - 定义文档/资源的名称

如果两个URL的scheme、host、domain和port都相同的话,就认为这两个URL是同源。

解决方案

跨域的解决方案有很多JSONP空iframe标签加form、代理、CROSJavaScript的跨源脚本API等方式。

  • CROS,全称为Cross Origin Resource Sharing,跨域资源共享。它是HTTP协议的一部分,允许服务端来指定哪些主机可以从这个服务端加载资源。工作量主要在后端。通过代码和配置文件等方式实现;
  • Nginx代理(开发环境下可以简单的使用webpackproxy)进行反向代理,原理是搭建一个中转服务器来转发请求规避跨域的问题。
  • JSONP只能发送GET请求(不推荐);
  • 空iframe发送POST请求可与上面结合使用(不推荐)。

实际解决办法

结合自己的项目实际,在SpringMVC的配置文件中配置cros的支持。
大致如下,按照自己实际需求进行修改(地址已脱敏):

<mvc:cors>
        <mvc:mapping path="/**"
                     allowed-origins="http://localhost:8080"
                     allowed-methods="POST, PUT, GET, OPTIONS, DELETE"
                     allowed-headers="Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token"
                     allow-credentials="true"
                     max-age="5000"
                     exposed-headers="Token"
        />
</mvc:cors>

Shiro的集成

本来以为解决了跨域的问题,就可以高枕无忧的调整业务代码了,哪成想,还有两个大问题需要解决。

登录成功会产生一个idjsessionidcookies,每次请求带着这个,来验证用户是否登录和是否有权限。正因为如此,产生了如下问题。

复杂请求

  • 复杂请求(比如请求携带某些请求头)会发送预请求,请求类型为OPTIONS,默认不会携带cookies、token等,也无法通过配置让其默认携带。

session超时

  • session是有时限的,过期访问时,shiro会重定向到配置文件里配置的loginUrl ,即默认去寻找Web工程根目录下的"/login.jsp"页面这与前后端分离的设想不符。需要使其返回的是Json格式的返回值,交由前端处理跳转登陆。

解决办法

  • 通过继承org.apache.shiro.web.filter.authc.FormAuthenticationFilter类,并重写isAccessAllowed方法,默认放行请求类型为OPTIONS的请求,其他类型请求的方式仍交由父类的方法处理。
  • 同上,重写onAccessDenied方法,使没有登录状态时返回json类型的数据,在前台拦截并跳转到首页。

代码如下

@Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        // 如果是复杂请求的预请求,请求类型为OPTIONS,而且默认不携带cookies信息,也无法通过配置使之默认携带相关信息
        // 所以会被Shiro拦截,导致真正的请求发送不出去。
        // 解决的办法有很多,这里采用了放行所有OPTIONS类型请求的办法,并不会产生安全问题
        if ("OPTIONS".equals(((HttpServletRequest) request).getMethod().toUpperCase())) {
            return true;
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }
@Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // Shiro在拦截请求验证登录状态的时候,如果没有登录,则会跳转到配置的loginUrl路径,默认是login.jsp
        // 这与前后端分离的精神不符。
        // 重写这个方法,使登录验证未通过,返回json给前端。交由前端统一处理
        HttpServletResponse res = (HttpServletResponse)response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setStatus(HttpServletResponse.SC_OK);
        res.setCharacterEncoding("UTF-8");
        PrintWriter writer = res.getWriter();
        Map<String, Object> map= new HashMap<>();
        map.put("code", 401);
        map.put("msg", "Not logged in");
        writer.write(JSON.toJSONString(map));
        writer.close();
        return false;
    }

关于Token的问题这里先不讨论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值