前言:前后端分离,业务分离,网关路由等已经成为当下web application开发的流行趋势。前端以单页面路由为核心的框架为主体,可以单独部署在nodejs或nginx上。后端以springboot为代表的分布式微服务框架为主体,可以独立运行在任何端口上。相互通过符合restful规范的接口访问或数据交换。在这样的开发模式下,首先需要解决的就是由于跨域而引起的访问,cookie传递以及权限管理问题。本文以时下最流行的Angular2,Springboot,Zuul,Shiro为例,提供最佳实践。

一、一般访问

开发中首先遇到的问题就是由于前端运行端口和后端运行端口不一致所造成的跨域访问。推荐在Springboot项目上增加过滤器:

@WebFilter
public class CorsFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
response.setHeader("Access-Control-Allow-Credentials","true");
chain.doFilter(req, res);
} @Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub } }

二、身份认证auth

当用户登录以后理论上我们可以在后端我们可以获取当前用户的session数据,可是依然存在问题。造成这个问题的主要原因是后端依靠sessionid来确认数据,正常情况下浏览器会将数据保存在cookie中,而在非跨域的环境中,浏览器的每一次访问都会携带自己的cookie信息。但是Angular2这样的异步框架http模块默认请求时不会携带cookie信息的。这个问题的解决方法是前端请求需要增加“withCredentials: true”字段:

httpOptions: {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true
}
this.http.get<Users>(global.loginUrl + 'getUsers', global.httpOptions);

仅仅如此还不够,如果我们的前端并不是直接访问后端服务,而是通过Zuul这样的网管路由做了代理访问。你会发现后端依然无法正确获取session。原因是Zuul默认是不转发请求头或会过滤掉一些重要的头信息。因此我们还需要在Zuul的配置文件中增加一条:

zuul:
routes:
<servername>
sensitiveHeaders: "*"

这样前端请求携带的cookie信息才会顺利被发送到后端服务,后端才能够获取到正确的session。

三、Shiro过滤器

准确的这个问题不是跨域造成的,根据目前HTML5的流行趋势,在发送Post和Put请求前会首先通过Options请求做探测。在没有配置Shiro过滤器的情况下,这都不是问题。可以一旦后端服务配置了根绝url的权限过滤,前端的请求又会出现问题。原因是Shiro的默认过滤器使用了重定向,而Options在重定向后认为地址不可达因此不会继续发送正确的请求。要解决这个问题,我们需要重写Shiro的FormAuthenticationFilter:

@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager, @Qualifier("authFilter") Filter filter) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, Filter> filters = new HashMap<>();
filters.put("authc", filter);
filters.put("roles", filter);
filters.put("perms", filter);
shiroFilterFactoryBean.setFilters(filters); Map<String, String> filterChainDefinitionMap = new HashMap<String, String>(); filterChainDefinitionMap.put("/*", "anon");
filterChainDefinitionMap.put("/auth/*", "authc");
filterChainDefinitionMap.put("/auth/admin/*", "roles[admin,administrator]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
} @Bean("authFilter")
public Filter authenticationFilter() {
return new FormAuthenticationFilter() {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (request instanceof HttpServletRequest) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
}
return super.isAccessAllowed(request, response, mappedValue);
} @Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
};
}
}

当然Shiro也为我们预留了接口,我们只需要按照需求配置即可。

四、总结

当下流行的前后端分离框架跨域是我们遇到的第一个问题,我们可以在服务端配置允许跨域访问来解决,具体方法推荐使用WebFilter过滤器。但是默认的rest请求sessionid,因此我们还需要让前端在请求头携带cookie。另外如果我们在前端展示与后端服务之前使用了网关还需要让网关服务允许所有的请求头通过而不要进行过滤。最后如果我们还使用了安全框架就必须让基于url权限管理功能放行所有的Options请求,以便让前端不会误认为请求地址不可达。

Angular2,Springboot,Zuul,Shiro跨域CORS请求踩坑实录的更多相关文章

  1. zuul+security跨域Cors问题解决

    zuul+security跨域Cors问题解决 简介 场景 在服务后台都会出现跨域cors问题,不过一般spring解决起来比较方便,在框架+框架的基础上,问题就显得特别明显了,各种冲突,不了解源码的 ...

  2. SpringBoot2.x整合Shiro出现cors跨域问题(踩坑记录)

    1. Springboot如何跨域? 最简单的方法是: 定义一个配置CorsConfig类即可(是不是简单且无耦合到令人发指) @Configuration public class CorsConf ...

  3. springboot webapi 支持跨域 CORS

    1.创建corsConfig 配置文件 @Configuration public class corsConfig { @Autowired varModel varModel_; @Bean pu ...

  4. 004. 前端跨域资源请求: JSONP/CORS/反向代理

    1.什么是跨域资源请求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有 ...

  5. SpringBoot设置支持跨域请求

    跨域:现代浏览器出全的考虑,在http/https请求时必须遵守同源策略,否则即使跨域的http/https 请求,默认情况下是被禁止的,ip(域名)不同.或者端口不同.协议不同(比如http.htt ...

  6. 跨域原因及SpringBoot、Nginx跨域配置

    目录 概述 简单请求 跨域解决方案 概述 SpringBoot跨域配置 Nginx跨域配置 概述 MDN文档 Cross-Origin Resource Sharing (CORS) 跨域的英文是Cr ...

  7. MVC跨域CORS扩展

    一般的基于浏览器跨域的主要解决方法有这么几种:1.JSONP       2.IFrame方式    3.通过flash实现  4.CORS跨域资源共享  ,这里我们主要关注的是在MVC里面的CORS ...

  8. 跨域post请求实现方案小结--转

    [名词解释] 跨域:https://developer.mozilla.org/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript 同源策略 ...

  9. 跨域CORS

    一.跨域CORS是什么 当一个资源从与该资源本身所在的服务器的域或端口不同的域或不同的端口请求一个资源时,浏览器会发起一个跨域 HTTP 请求.出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求 ...

随机推荐

  1. 提高php代码质量的36个技巧的摘录

    17.不要直接使用 $_SESSION 变量 简单例子: $_SESSION['username'] = $username; $username = $_SESSION['username'];   ...

  2. windows配置iis网站域名

    1.在iis 中添加网站,网站名和主机名设置为test.com 2.在C:\Windows\System32\drivers\etc找到host文件,添加 127.0.0.1 test.com 127 ...

  3. python服务器端、客户端的模型,客服端发送请求,服务端进行响应(web.py)

    服务器端.客户端的模型,客服端发送的请求,服务端的响应 相当于启动了一个web server install web.py 接口框架用到的包 http://webpy.org/tutorial3.zh ...

  4. 线程属性pthread_attr_t简介

    本文编辑整理自: http://hi.baidu.com/7828058/blog/item/256e16decd1a385e94ee3784.html http://www.ibm.com/deve ...

  5. 一个快速检测系统CPU负载的小程序

    原理说明 在对服务器进行维护时,有时也遇到由于系统 CPU(利用率)负载过高导致业务中断的情况.服务器上可能运行多个进程,查看单个进程的 CPU 都是正常的,但是整个系统的 CPU 负载可能是异常的. ...

  6. Tomcat8.5 升级tomcat版本导致出现异常,Base64不存在

    Tomcat8.5 升级tomcat版本导致出现异常,Base64不存在 原因分析: 由于tomcat由7升级到8.5导致Base64的引用路径错误,默认引用为8.5中的jar, 解决方案: 修改引用 ...

  7. 20145306 《网络攻防》 MSF基础应用

    20145306张文锦<网络对抗>MSF应用 Adobe阅读器渗透攻击 两台虚拟机,其中一台为kali,一台为windows xp sp3,并保证两台虚拟机可以ping通. 实验过程 进入 ...

  8. 超频真的不难!G3258超频4.5GHz全攻略

    奔腾G3258搭配主板详解 [pconline 应用]目前DIY市场上最火热的装机组合莫过于奔腾20周年纪念版处理器G3258搭配B85芯片组主板,只要通过适当的超频,相对较低投入也能来不错的性能体验 ...

  9. 解决Navicat Premium 12 连接oracle数据库出现ORA-28547的问题

    1. 出现的问题... 下午工作时想连接Oracle数据库,使用的是Navicat Premium 12 . 数据库地址.用户名.密码.端口号都没有问题,但出现了ORA-28547:connectio ...

  10. SQLSERVER中order by ,group by ,having where 的先后顺序

    SELECT [Name]  FROM [LinqToSql].[dbo].[Student]  where name='***' group  by  name    having (name='* ...