一、Gateway鉴权实现方案
网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性。
RBAC(Role-Based Access Control)基于角色访问控制,目前使用最为广泛的权限模型。相信大家对这种权限模型已经比较了解了。此模型有三个用户、角色和权限,在传统的权限模型用户直接关联加了角色,解耦了用户和权限,使得权限系统有了更清晰的职责划分和更高的灵活度
1、添加依赖
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
2、实现代码
@Configuration @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { @Autowired JwtTokenUtil jwtTokenUtil; @Autowired(required = false) JedisUtil jedisUtil; private String cachePrefix = "km-gateway-"; @Value("${spring.redis.expired}") private Integer expiredSecond;//600000,10m @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders httpHeaders = request.getHeaders(); exchange.getRequest().getURI(); String requestUri = request.getPath().pathWithinApplication().value(); String token = null; if (httpHeaders != null && httpHeaders.containsKey("token") && !httpHeaders.get("token").isEmpty()) { token = httpHeaders.get("token").get(0); } // AuthenticateRequest if (StringUtil.isBlank(token)) { // String message = "You current request uri do not have permission or auth."; // return getVoidMono(exchange, message); return chain.filter(exchange); } String userAccountId = jwtTokenUtil.getUserAccountIdFromToken(token); boolean hasPermission = checkPermission(userAccountId, requestUri); String username = jwtTokenUtil.getUsernameFromToken(token); String redisSetUrlKey = cachePrefix.concat("url-").concat(username); // log.info("###### hasPermission.2=" + hasPermission); if (hasPermission) { jedisUtil.SetAndTime(redisSetUrlKey, expiredSecond, requestUri); } else { String message = "You current request uri do not have permission or auth."; // log.warn(message); return getVoidMono(exchange, message); } jwtTokenUtil.isValid(token); return chain.filter(exchange); } @Override public int getOrder() { return 0; } //根据角色权限进行权限控制 private boolean checkPermission(String userId, String requestUrl) { return false; } private Mono<Void> getVoidMono(ServerWebExchange exchange, String body) { exchange.getResponse().setStatusCode(HttpStatus.OK); byte[] bytes = body.getBytes(StandardCharsets.UTF_8); DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes); return exchange.getResponse().writeWith(Flux.just(buffer)); } }
二、Gateway跨域解决方案
在SpringCloud项目中,前后端分离目前很常见,在调试时会遇到前端页面通过不同域名或IP访问微服务的后台,此时,如果不加任何配置,前端页面的请求会被浏览器跨域限制拦截,所以,业务服务常常会添加跨域配置
1、配置类实现
@Configuration public class GulimallCorsConfiguration { /** * 添加跨域过滤器 * @return */ @Bean public CorsWebFilter corsWebFilter(){ //基于url跨域,选择reactive包下的 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); // 跨域配置信息 CorsConfiguration configuration = new CorsConfiguration(); // 允许跨域的头 configuration.addAllowedHeader("*"); // 允许跨域的请求方式 configuration.addAllowedMethod("*"); // 允许跨域的请求来源 configuration.addAllowedOrigin("*"); // 是否允许携带cookie跨域 configuration.setAllowCredentials(true); // 任意url都要进行跨域配置 source.registerCorsConfiguration("/**", configuration); return new CorsWebFilter(source); } }
注: SpringCloudGateWay中跨域配置不起作用 ,原因是SpringCloudGetway是 Springwebflux 的而不是SpringWebMvc的,所以我们需要导入的包导入错了
2、配置文件配置
server: port: 10010 spring: application: name: gatewayservice cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: "https://www.xx.com" # 允许那些网站跨域访问 allowedMethods: "GET" # 允许那些Ajax方式的跨域请求 allowedHeaders: "*" # 允许请求头携带信息 allowCredentials: "*" # 允许携带cookie maxAge: 360000 # 这次跨域有效期于相同的跨域请求不会再预检
文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群
创作不易,如果觉得文章不错,可以点赞 收藏 评论
你的支持和鼓励是我创作的动力❗❗❗
官网:Doker 多克; 官方旗舰店:首页-Doker 多克 多克创新科技企业店-淘宝网 全品优惠