1.Spring Cloud Gateway及Security认证
1.Spring Cloud Gateway简介Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。2.创建工程本文我们采用最新的Spring Cloud 版本“Finchley.SR2”,注意该版本对应Spring Boot为2x。官方推...
1.Spring Cloud Gateway简介
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。
2.创建工程
本文我们采用最新的Spring Cloud 版本“Finchley.SR2”,注意该版本对应Spring Boot为2x。官方推荐的是:2.0.6.RELEASE版本。
父项目导入如下包:
<dependencyManagement>
<dependencies>
<!-- spring boot依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<!--zookeeper依赖-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<!--validator依赖-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.9.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
gateway网关服务导入如下jar:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<!--zookeeper依赖-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.uaf.credit</groupId>
<artifactId>uaf-credit-api</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
父项目统一管理jar包的版本,子项目就不必再添加jar对应的版本号
网关服务的yml配置如下:
server:
port: 8817
spring:
application:
name: uaf-credit-gateway
security:
user:
name: wxt
password: wxt2016
cloud:
gateway:
routes:
- id: credit-auth-route
uri: http://10.168.xx.xx:8820/credit-auth/v1
predicates:
- Path=/credit-auth/v1/* #路径匹配,匹配所有请求路径以/credit-auth开头的用户请求
logging:
config: classpath:logback.xml
3.Spring Cloud Gateway过滤器
Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义。全局过滤器是一系列特殊的过滤器,会根据条件应用到所有路由中。网关过滤器是更细粒度的过滤器,作用于指定的路由中。
我们可以配置多个GlobalFilter过滤器,通过指定getOrder()方法的优先级来配置过滤器的执行顺序。
@Component
public class RequestAuthFilter implements GlobalFilter, Ordered {
/**
* 请求方式验证过滤器
* @param exchange
* @param chain
* @return reactor.core.publisher.Mono<java.lang.Void>
* 作者:will
* 日期:2019/4/4 14:46
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String method = serverHttpRequest.getMethodValue();
if(!"POST".equals(method)){
ServerHttpResponse response = exchange.getResponse();
String message= new ResponseUtils().CreditRespMsg(CreditException.ERR_100008,"非法请求",null);
byte[] bits = message.getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//指定编码,否则在浏览器中会中文乱码
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
/**
* 优先级
* @return int 数字越大优先级越低
* 作者:will
* 日期:2019/4/4 13:36
*/
@Override
public int getOrder() {
return 0;
}
}
4.Spring boot Security认证
Spring Security致力于为Java应用提供认证和授权管理。它是一个强大的,高度自定义的认证和访问控制框架,这句话包括两个关键词:Authentication(认证)和 Authorization(授权,也叫访问控制)。
需要安全认证的服务需要导入如下Jar:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
yml配置:
server:
port: 8820
servlet:
context-path: /credit-auth
spring:
application:
name: uaf-credit-auth
security:
user:
name: wxt
password: wxt2016
roles:
- USER
logging:
config: classpath:logback.xml
接下来配置认证类:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/**表示所有的访问都必须进行认证处理后才可以正常进行*/
http.httpBasic().and().authorizeRequests().anyRequest().fullyAuthenticated();
/**所有的Rest服务一定要设置为无状态,以提升操作性能*/
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
/**关闭csrf避免POST请求时出现401异常*/
http.csrf().disable();
http.authorizeRequests().antMatchers(org.springframework.http.HttpMethod.GET).permitAll();
}
}
这里有个问题,外面的服务若请求我们的服务需要进行Security认证,但我们的网关应该需要免认证。
我们通过Gateway的GlobalFilter过滤器的方式实现:
@Component
public class OAuthSignatureFilter implements GlobalFilter, Ordered {
/**授权访问用户名*/
@Value("${spring.security.user.name}")
private String securityUserName;
/**授权访问密码*/
@Value("${spring.security.user.password}")
private String securityUserPassword;
/**
* OAuth过滤器
* @param exchange
* @param chain
* @return reactor.core.publisher.Mono<java.lang.Void>
* 作者:will
* 日期:2019/4/4 13:36
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
/**oauth授权*/
String auth= securityUserName.concat(":").concat(securityUserPassword);
String encodedAuth = new sun.misc.BASE64Encoder().encode(auth.getBytes(Charset.forName("US-ASCII")));
//注意Basic后面有空格
String authHeader= "Basic " +encodedAuth;
//向headers中放授权信息
ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().header("Authorization",authHeader).build();
//将现在的request变成change对象
ServerWebExchange build =exchange.mutate().request(serverHttpRequest).build();
return chain.filter(build);
}
/**
* 优先级
* @return int 数字越大优先级越低
* 作者:will
* 日期:2019/4/4 13:36
*/
@Override
public int getOrder() {
return 2;
}
5.新增自定义过滤器
gateway里面可以自定义普通filter,也可以创建自定义的GlobalFilter,我们通过继承AbstractGatewayFilterFactory实现自定义过滤器。
yml新增如下配置:
spring:
application:
name: uaf-credit-gateway
security:
user:
name: wxt
password: wxt2016
cloud:
gateway:
routes:
- id: credit-auth-route
uri: http://10.168.xx.xx:8820/credit-auth/v1
predicates:
- Path=/credit-auth/v1/* #路径匹配,匹配所有请求路径以/credit-auth开头的用户请求
filters:
- CreditFilter #注意与定义的过滤器类名一致
新增CreditFilter.java类,自定义过滤器的优先级低于GlobalFilter
@Configuration
public class CreditFilter extends AbstractGatewayFilterFactory<CreditFilter.Config> {
public CreditFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
MySlf4j.textInfo("进入自定义Credit过滤器");
return (exchange, chain) -> {
String jwtToken = exchange.getRequest().getHeaders().getFirst("Authorization");
//校验jwtToken的合法性
if (jwtToken != null) {
// 合法
// 将用户id作为参数传递下去
return chain.filter(exchange);
}
//不合法(响应未登录的异常)
ServerHttpResponse response = exchange.getResponse();
//设置headers
HttpHeaders httpHeaders = response.getHeaders();
httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
//设置body
String warningStr = "未登录或登录超时";
DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
return response.writeWith(Mono.just(bodyDataBuffer));
};
}
public static class Config {
}
@Bean
public CreditFilter creditFileterFactory() {
return new CreditFilter();
}
}
至此我们的Gateway及相关的授权认证配置完成。
更多推荐
所有评论(0)