企业实战之Spring拦截器《解决跨域问题》
来源:互联网 发布:真空上街 知乎 编辑:程序博客网 时间:2024/06/10 01:59
本章我们主要讲解后端开发对于跨域问题的解决方案,下面我们先来了解一下跨域。
跨域是什么?
跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站时,浏览器出于安全考虑,自动阻止了对跨域服务的访问(包括对后端数据的增删改查请求),这里浏览器统一遵循了一种策略,这个策略就是同源策略,同源策略也是浏览器最核心、最基本的安全功能。
什么情况下会发生跨域?
从上面的表格中我们可以看出,协议、域名、端口三者之间任意一与当前页面地址不同都会引起跨域问题。
企业开发中出现跨域问题情况举例
- 前后端分离的的开发模式中,前端开发人员使用本地(http://localhost)去调用我们后端准备的联调环境接口服务(http://fe-api.zhuma.com) 。
- 当项目变得庞大,业务变得复杂,很可能会出现想要直接调用第三方的某些服务来完成业务功能,这时便出现了跨域问题。
解决方案
在我们的实际开发过程中,我们会使用 CORS方式,自己定义个拦截器 对开发、测试环境解决跨域问题,线上环境如果出现跨域问题会使用nginx做个代理中转的这种方式,这里说明下线上环境尽量保证 接口、页面 同一域名。
如果你的需求是只对某些特定的接口允许跨域访问,在springmvc项目开发中,你可以使用自定义注解+下面提到的拦截器的方式去处理,如果你还是不会写,可以在文章末尾留言或直接加公众号联系我O(∩_∩)O。
下面我们说下具体解决的代码逻辑:
- CORS方式
这是W3C提供的另一种跨域方式,作为一项标准的跨域规范,我们使用我们自己定义的拦截器进行统一设置实现解决测试环境上的跨域问题。下面我给出使用spirng boot时的相关代码。
拦截器主功能类
package com.zhuma.demo.comm.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.env.Environment;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import com.zhuma.demo.comm.enums.EnvironmentEnum;import com.zhuma.demo.comm.util.StringUtil;/** * @desc 允许跨域拦截器 * * @author zhumaer * @since 6/20/2017 3:00 PM */@Componentpublic class AllowCrossDomainInterceptor implements HandlerInterceptor { @Autowired private Environment env; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!EnvironmentEnum.isProdEnv(env)) {//仅在非正式环境下生效 String origin = request.getHeader("Origin"); response.setHeader("Access-Control-Allow-Origin", StringUtil.isEmpty(origin) ? "*" : origin); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, PATCH"); response.setHeader("Access-Control-Max-Age", "0"); response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("XDomainRequestAllowed","1"); } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // nothing to do } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // nothing to do }}
环境常量枚举类
public enum EnvironmentEnum { PROD,//生产 FE,//联调 QA,//测试 STG;//仿真 public static boolean isProdEnv(Environment env) { Assert.notNull(env, "env parameter not null."); return EnvironmentEnum.PROD.name().equalsIgnoreCase(env.getProperty("spring.profiles.active")); } @Override public String toString() { return this.name(); }}
拦截器配置类
package com.zhuma.demo.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import com.zhuma.demo.interceptor.AllowCrossDomainInterceptor;import com.zhuma.demo.comm.constants.Constants;/** * @desc WEB配置类 * * @author zhumaer * @since 6/23/2017 14:11 PM */@Configurationpublic class WebAppConfig extends WebMvcConfigurerAdapter { @Autowired private AllowCrossDomainInterceptor allowCrossDomainInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { String apiUri = "/" + Constants.API_ROOT + "/**"; //跨域拦截 registry.addInterceptor(allowCrossDomainInterceptor).addPathPatterns(apiUri); }}
后端服务做代理
使用nginx这种服务器,在后端做一个中转。本文我们不是重点讲这种方式,所以想了解的自行百度下吧。JSONP
这种方式缺点是只能支持GET方法的请求,我看到一些公司为了支持JSONP将后端的添加、修改、删除功能接口都改为GET方式,这种是很不建议的,这样会存在安全隐患。如果你用的是spring boot的话可以参考下AbstractJsonpResponseBodyAdvice这个类的使用。
最后
后面我们会在讲解几个关于拦截器在企业开发中的实战的例子,之后会讲解 统一登录校验、统一的参数校验、接口权限校验等。
欢迎关注我们的公众号或加群,等你哦!
- 企业实战之Spring拦截器《解决跨域问题》
- 企业实战之Spring拦截器+注解实现《登录校验》
- 企业实战之Spring拦截器《统一参数校验》
- 解决spring-mvc spring拦截器 跨域问题
- springBoot之拦截器解决前端跨域问题
- 企业实战之spring增强器实现《全局异常处理器》
- spring解决sql注入问题:自定义拦截器
- 关于spring mvc拦截器拦截js文件等导致无法正常使用问题的解决
- 关于spring mvc拦截器拦截js文件等导致无法正常使用问题的解决
- 关于spring mvc拦截器拦截js文件等导致无法正常使用问题的解决
- spring boot之拦截器
- 企业实战之Spring项目《hibernate validator+Assert参数校验》
- CXF实战之拦截器Interceptor(四)
- CXF实战之自定义拦截器(五)
- 实战window.name解决跨域问题
- 解决Spring Boot 拦截器注入service为空的问题
- Spring+MYBatis企业应用实战
- spring mvc 拦截器路径问题,只拦截固定后缀
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Query was empty异常原因?
- *HMK 1 for NOIP (130/300)
- 使用pyinstaller将python脚本转换成exe可执行文件
- 列表页面传递一个id给对应的详情页面(做项目时的简单总结)
- Linux静态库和动态库
- 企业实战之Spring拦截器《解决跨域问题》
- 从c语言中常用变量的生命周期,作用域,默认值,内存区域及链接属性
- vue.js 表单控件 输入绑定 v-model的使用
- vnc, vncserver, ssh的locale问题
- 大型网站技术架构
- 升级OSX High Sierra 10.13遇到一些问题及解决方法
- linux socket网络编程实例
- 自制ToolBox,支持自由展开多组
- typedef