路由:她会把外部全部对请求转发到具体的微服务实例上,是实现外部访问同一接口的基础html
过滤: 就是权限的检查, 判断当前的请求是否有权限区访问那些服务集群java
搭建后台网关:spring
导入eureka - client, 它自己也是一个客户端,须要注册进eureka后端
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
过滤器, 重写下面的ZuulFilter能够实现自定义的过滤规则, 每一个方法的含义都经过注释的方式写在了方法头安全
网关的过滤器 @Component public class WebManagerFilter extends ZuulFilter { /** * 指定过滤器的类型 pre :能够在请求被路由以前调用 route :在路由请求时候被调用 post :在route和error过滤器以后被调用 error :处理请求时发生错误时被调用 * @return */ @Override public String filterType() { return "pre"; } /** * 指定过滤器的优先级, 0表示优先执行, 由于咱们能够写不少个过滤器 * @return */ @Override public int filterOrder() { return 0; } /** * 当前过滤器是否开启, true表示开启 * @return */ @Override public boolean shouldFilter() { return true; } /** * 过滤器执行逻辑, 返回任意Object类型的值,都表示放行,包括null * 若是不想日后继续执行了,就使用 setSendZullResponse(false) * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { System.out.println("通过了后台的过滤器"); return null; } }
咱们能够经过RequestContext的实例对象,获取出请求头,请求parms,请求ip等信息, 针对不一样的信息能够作出不一样的处理前后端分离
黑白名单ide
好比咱们能够在网关中禁用掉恶意访问的ip地址微服务
验证权限工具
若是项目是先后端分离使用jwt等工具生成token放在请求头中作安全验证,咱们也能在网关中对请求头作出初步解析处理post
防止抓包
还能根据用户请求中发送过来的请求参数作验证签名处理, 防止数据在传输过程当中被恶意篡改
此外,网关会过滤掉一些请求的请求头,若是请求头是咱们本身定义的,就好比下面的Authrization, 通过网关后的请求的头信息会丢失,进而致使下面的这段代码失效, 获取不出头信息,就没办法验证token的合法性
解决办法: 选着添加添加一条配置信息 sensitive-headers:
将这个配置置空,意为清空网关要过滤的请求头
RequestContext currentContext = RequestContext.getCurrentContext(); String header = currentContext .getRequest().getHeader("Authorization"); System.err.println("zull header "+header); // 判断是否存在header if (!"".equals(header)&&header!=null){ System.err.println("转发header"); currentContext.addZuulRequestHeader("Authorization",header); }
使用过滤器作验证的逻辑以下,验证携带在请求头中的token信息以下:
这个方法的特色就是, 只要他能在遇到 return null
就表示成功完成了验证的逻辑
1. 导入 common,咱们要使用它的jwtUtil @Override public Object run() throws ZuulException { System.err.println("通过了后台的过滤器"); RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); // 获取出请求头 String header = request.getHeader("Authorization"); // 放行zuul的第一次请求 todo 我并无触发这个方法的执行 if (request.getMethod().equals("OPTIONS")){ System.err.println("OPTIONS"); return null; } // 放行登陆请求 if (request.getRequestURL().indexOf("login")>0){ return null; } if (StringUtils.isNotBlank(header)){ if (header.startsWith("Bearer ")){ String token = header.substring(7); if (StringUtils.isNotBlank(token)){ System.out.println("token=="+token); try{ Claims claims = jwtUtil.parseJWT(token); String roles =(String) claims.get("roles"); System.out.println("roles=="+roles); // 对admin放行, if (roles.equals("admin")){ return null; } // todo 转发头信息,我改了配置文件, 让zuul不过滤任何头信息 // 其余状况, 终止访问 currentContext.setSendZuulResponse(false); }catch (Exception e){ // 解析token出现的异常,说明token有问题, 终止本次请求 System.out.println("token出错了,终止本次访问: "+e); currentContext.setSendZuulResponse(false); } } } } currentContext.setSendZuulResponse(false); currentContext.getResponse().setContentType("text/html;chatset=utf-8"); try { currentContext.getResponse().getWriter().write("权限不足"); } catch (IOException e) { e.printStackTrace(); } return null; }