6.认证服务对接网关
6.1 新建网关工程changgou_gateway_web
- changgou_gateway添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
- 新建工程changgou_gateway_web,并创建启动类
package com.changgou.web.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class WebGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(WebGatewayApplication.class,args);
}
}
- 创建application.yml
spring:
application:
name: gateway-web
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
- id: changgou_goods_route
uri: lb://goods
predicates:
- Path=/api/album/**,/api/brand/**,/api/cache/**,/api/categoryBrand/**,/api/category/**,/api/para/**,/api/pref/**,/api/sku/**,/api/spec/**,/api/spu/**,/api/stockBack/**,/api/template/**
filters:
#- PrefixPath=/brand
- StripPrefix=1
#用户微服务
- id: changgou_user_route
uri: lb://user
predicates:
- Path=/api/user/**,/api/address/**,/api/areas/**,/api/cities/**,/api/provinces/**
filters:
- StripPrefix=1
#认证微服务
- id: changgou_oauth_user
uri: lb://user-auth
predicates:
- Path=/api/oauth/**
filters:
- StripPrefix=1
redis:
host: 192.168.200.128
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka
instance:
prefer-ip-address: true
management:
endpoint:
gateway:
enabled: true
web:
exposure:
include: true
6.2 网关全局过滤器
新建过滤器类AuthorizeFilter,对请求进行过滤
业务逻辑:
1)判断当前请求是否为登录请求,是的话,则放行
2) 判断cookie中是否存在信息, 没有的话,拒绝访问
3)判断redis中令牌是否存在,没有的话,拒绝访问
package com.changgou.web.gateway.filter;
import com.changgou.web.gateway.service.AuthService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Autowired
private AuthService authService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//1.判断当前请求路径是否为登录请求,如果是,则直接放行
String path = request.getURI().getPath();
if ("/api/oauth/login".equals(path) || !UrlFilter.hasAuthorize(path) ){
//直接放行
return chain.filter(exchange);
}
//2.从cookie中获取jti的值,如果该值不存在,拒绝本次访问
String jti = authService.getJtiFromCookie(request);
if (StringUtils.isEmpty(jti)){
//拒绝访问
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
//3.从redis中获取jwt的值,如果该值不存在,拒绝本次访问
String jwt = authService.getJwtFromRedis(jti);
if (StringUtils.isEmpty(jwt)){
//拒绝访问
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
//4.对当前的请求对象进行增强,让它会携带令牌的信息
request.mutate().header("Authorization","Bearer "+jwt);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
新建业务逻辑类AuthService
package com.changgou.web.gateway.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
//从cookie中获取jti的值
public String getJtiFromCookie(ServerHttpRequest request) {
HttpCookie httpCookie = request.getCookies().getFirst("uid");
if (httpCookie != null){
String jti = httpCookie.getValue();
return jti;
}
return null;
}
//从redis中获取jwt
public String getJwtFromRedis(String jti) {
String jwt = stringRedisTemplate.boundValueOps(jti).get();
return jwt;
}
}
测试:
清除postman中的cookie数据,在未登录的情况下,并访问: http://localhost:8001/api/user 。会返回401异常信息
访问:http://localhost:8001/api/oauth/login,并重新测试。可以发现测试通过,拿到返回结果数据