本文主要是介绍微服务之网关安全基于Zuul并实现网关限流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
微服务网关安全
微服务架构下的问题
处理安全和业务逻辑耦合,增加了复杂性和变更成本
随着业务节点增加,认证服务器压力增大
多个微服务同时暴露,增加了外部访问的复杂性
通过网关处理流程
1、请求令牌。2、转发请求。3、返回令牌。4、转发令牌各客户端应用。5、携带令牌发送请求。6、校验令牌。7、返回校验结果信息。8、访问微服务。
实例
引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- https://mvnrepository.com/artifact/com.marcosbarbero.cloud/spring-cloud-zuul-ratelimit --><dependency><groupId>com.marcosbarbero.cloud</groupId><artifactId>spring-cloud-zuul-ratelimit</artifactId><version>2.3.0.RELEASE</version></dependency>
</dependencies>
增加配置文件application.yml
zuul:routes:token:url: http://localhost:8085order:url: http://localhost:9080#敏感头,有三个敏感头,cookie,set-cookie,Authorizationsensitive-headers:
增加验证token过滤器
/*** 验证token*/
@Component
@Slf4j
public class OAuthFilter extends ZuulFilter {@Autowiredprivate RestTemplate restTemplate;/*** 提供四种过滤类型,pre-请求前,post-请求之后,error-出错之后,route-控制路由* @return*/public String filterType() {return "pre";}/*** 过滤器执行顺序* @return*/public int filterOrder() {return 1;}/*** 过滤器是否起作用,true,启用过滤器* @return*/public boolean shouldFilter() {return true;}/*** 要写的业务逻辑* @return* @throws ZuulException*/public Object run() throws ZuulException {log.info("oauth start");RequestContext requestContext=RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//请求开头是不是以token开头的,发往认证服务器的请求不用验证if(StringUtils.startsWith(request.getRequestURI(),"/token")){return null;}String requestHeader=request.getHeader("Authorization");if(StringUtils.isBlank(requestHeader)){return null;}if(!StringUtils.startsWithIgnoreCase(requestHeader,"bearer ")){return null;}try{TokenInfo tokenInfo=getTokenInfo(requestHeader);request.setAttribute("tokenInfo",tokenInfo);}catch(Exception e){log.info("get token info fail:",e);}return null;}private TokenInfo getTokenInfo(String requestHeader) {String token=StringUtils.substringAfter(requestHeader,"bearer ");String oauthServiceUrl="http://localhost:8085/oauth/check_token";HttpHeaders httpHeaders=new HttpHeaders();httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);httpHeaders.setBasicAuth("gateway","123456");//只能用这个map,用hashmap什么的,报错MultiValueMap<String,String> params=new LinkedMultiValueMap<String, String>();params.put("token", Collections.singletonList(token));HttpEntity<MultiValueMap<String,String>> entity=new HttpEntity<MultiValueMap<String, String>>(params,httpHeaders);ResponseEntity<TokenInfo> response=restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);log.info("token info:{}",response.getBody().toString());return response.getBody();}
}
创建自定义token响应,通过check_token接口拿到的token信息
@Data
public class TokenInfo {/*** token 是不是可用的*/private boolean active;/*** token是发往哪个客户端应用*/private String client_id;/*** 这个令牌的具有的权限*/private String[] scope;/*** 这个令牌发给哪个用户*/private String user_name;/*** 这个令牌哪些客户端ID可以访问*/private String[] aud;/*** 这个令牌的过期时间*/private Date exp;/*** 这个令牌所对应的用户的访问权限*/private String[] authorities;}
增加授权过滤器,在验证token过滤器之后执行,故filterOrder设置比验证token过滤器要大
/*** 授权过滤器*/
@Component
@Slf4j
public class AuthorizationFilter extends ZuulFilter {public String filterType() {return "pre";}public int filterOrder() {return 3;}public boolean shouldFilter() {return true;}public Object run() throws ZuulException {log.info("authorization start");RequestContext requestContext=RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();/*** 权限判断,是否需要认证*/if(isNeedAuth(request)){TokenInfo tokenInfo = (TokenInfo) request.getAttribute("tokenInfo");if(tokenInfo!=null&&tokenInfo.isActive()){if(!hasPermission(tokenInfo,request)){log.info("audit log update fail 403");handleError(403,requestContext);}requestContext.addZuulRequestHeader("username",tokenInfo.getUser_name());}else{if(!StringUtils.startsWith(request.getRequestURI(),"/token")){log.info("audit log update fail 401");handleError(401,requestContext);return null;}}}else{}return null;}/*** 模拟获取权限请求,50%的概率报403* @param tokenInfo* @param request* @return*/private boolean hasPermission(TokenInfo tokenInfo, HttpServletRequest request) {
// return RandomUtils.nextInt()%2==0;return true;}private void handleError(int i, RequestContext requestContext) {requestContext.getResponse().setContentType("application/json");requestContext.setResponseStatusCode(i);requestContext.setResponseBody("{\"message\":\"auth fail\"}");requestContext.setSendZuulResponse(false);}private boolean isNeedAuth(HttpServletRequest request) {return true;}
}
zuul限流配置
pom文件增加
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.marcosbarbero.cloud/spring-cloud-zuul-ratelimit -->
<dependency><groupId>com.marcosbarbero.cloud</groupId><artifactId>spring-cloud-zuul-ratelimit</artifactId><version>2.3.0.RELEASE</version>
</dependency>
yml配置文件增加限流配置
zuul:routes:token:url: http://localhost:8085order:url: http://localhost:9080#敏感头,有三个敏感头,cookie,set-cookie,Authorizationsensitive-headers:ratelimit:enabled: true #限流是否起作用repository: jpa #存储位置default-policy-list: #默认策略- limit: 2quota: 1refresh-interval: 3type:- url- httpmethodpolicy-list: #针对于上面配置具体的服务限流规则token:- limit: 2quota: 1refresh-interval: 3type:- url- httpmethod
测试
注:3秒之内连续发送请求,报429错误,超过3秒,返回200
这篇关于微服务之网关安全基于Zuul并实现网关限流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!