Skip to content

Commit

Permalink
support example use sureness protect spring gateway (dromara#97)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsun28 authored May 11, 2021
1 parent 5ebf102 commit ab343ca
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 0 deletions.
1 change: 1 addition & 0 deletions samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<module>jfinal-sureness</module>
<module>solon-sureness</module>
<module>solon-plugin-sureness</module>
<module>spring-gateway-sureness</module>
<module>zuul-sureness</module>
</modules>
</project>
6 changes: 6 additions & 0 deletions samples/spring-gateway-sureness/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# sureness-gateway

> Spring Gateway integrates Sureness to provide API authentication and authorization at the gateway.


3 changes: 3 additions & 0 deletions samples/spring-gateway-sureness/README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# sureness-gateway

> Spring Gateway 集成 Sureness 在网关层面提供API的认证鉴权。
59 changes: 59 additions & 0 deletions samples/spring-gateway-sureness/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>samples</artifactId>
<groupId>com.usthe.sureness</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-gateway-sureness</artifactId>

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.2</spring-cloud.version>
<sureness-core.version>1.0.3</sureness-core.version>
</properties>
<dependencies>
<dependency>
<groupId>com.usthe.sureness</groupId>
<artifactId>sureness-core</artifactId>
<version>${sureness-core.version}</version>
</dependency>

<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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.4.RELEASE</version>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @author tomsun28
*/
@SpringBootApplication
public class GatewayApplication {

public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package gateway.sureness;


import com.usthe.sureness.DefaultSurenessConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
* sureness config
* @author tomsun28
* @date 23:38 2019-09-29
*/
@Configuration
public class SurenessConfiguration {

/**
* new sureness default config bean
* @return default config bean
*/
@Bean
public DefaultSurenessConfig surenessConfig() {
return new DefaultSurenessConfig(DefaultSurenessConfig.SUPPORT_SPRING_REACTIVE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package gateway.sureness;

import com.usthe.sureness.mgt.SurenessSecurityManager;
import com.usthe.sureness.processor.exception.*;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;

/**
* sureness filter
* @author tomsun28
* @date 2021/4/28 23:23
*/
public class SurenessFilter implements GatewayFilter, Ordered {

private static final Logger logger = LoggerFactory.getLogger(SurenessFilter.class);

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
try {
SubjectSum subject = SurenessSecurityManager.getInstance().checkIn(request);
// You can consider using SurenessContextHolder to bind subject in threadLocal
// if bind, please remove it when end
if (subject != null) {
SurenessContextHolder.bindSubject(subject);
}
} catch (IncorrectCredentialsException | UnknownAccountException | ExpiredCredentialsException e1) {
logger.debug("this request is illegal");
return responseWrite(exchange, HttpStatus.UNAUTHORIZED, e1.getMessage(),null);
} catch (NeedDigestInfoException e5) {
logger.debug("you should try once again with digest auth information");
return responseWrite(exchange, HttpStatus.UNAUTHORIZED,
"try once again with digest auth information",
Collections.singletonMap("WWW-Authenticate", e5.getAuthenticate()));
} catch (UnauthorizedException e5) {
logger.debug("this account can not access this resource");
return responseWrite(exchange, HttpStatus.FORBIDDEN, e5.getMessage(),null);
} catch (RuntimeException e) {
logger.error("other exception happen: ", e);
return responseWrite(exchange, HttpStatus.FORBIDDEN, e.getMessage(),null);
}

return chain.filter(exchange).doFinally(x -> SurenessContextHolder.unbindSubject());
}

@Override
public int getOrder() {
return 0;
}

/**
* write response json data
* @param exchange content
* @param statusCode statusCode
* @param message message
*/
private Mono<Void> responseWrite(ServerWebExchange exchange, HttpStatus statusCode,
String message, Map<String,String> headers) {

exchange.getResponse().setStatusCode(statusCode);
if (headers != null) {
headers.forEach((key, value) -> exchange.getResponse().getHeaders().add(key, value));
}
if (message != null) {
return exchange.getResponse().writeWith(Flux.create(sink -> {
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
DataBuffer dataBuffer= nettyDataBufferFactory.wrap(message.getBytes(StandardCharsets.UTF_8));
sink.next(dataBuffer);
sink.complete();
}));
} else {
return exchange.getResponse().setComplete();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gateway.sureness;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

/**
* surenessFilter factory
* @author tomsun28
* @date 2021/4/28 23:40
*/
@Component
public class SurenessGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {

@Override
public GatewayFilter apply(Object config) {
return new SurenessFilter();
}

@Override
public String name() {
return "SurenessAuth";
}
}
10 changes: 10 additions & 0 deletions samples/spring-gateway-sureness/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
spring:
cloud:
gateway:
default-filters:
- SurenessAuth
routes:
- id: route1
uri: https://www.bing.com
predicates:
- Path=/api/**
43 changes: 43 additions & 0 deletions samples/spring-gateway-sureness/src/main/resources/sureness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## -- sureness.yml document dataSource-- ##

# load api resource which need be protected, config role who can access these resource.
# resources that are not configured are also authenticated and protected by default, but not authorized
# eg: /api/v1/bar===post===[role1] means /api/v1/bar===post can be access by role1
# eg: /api/v3/foo===get===[] means /api/v3/foo===* can not be access by any role
resourceRole:
- /api/v1/bar/*===get===[role1,role2,role3]
- /api/v1/bar===post===[role1]
- /api/v2/bar===put===[role2]
- /api/v2/foo===get===[role3]
- /api/v3/foo===get===[]

# load api resource which do not need be protected, means them need be excluded.
# these api resource can be access by everyone
# eg: /**/*.png===* means get/post/put/delete/patch any url suffixed with `.png` can be access by everyone
excludedResource:
- /api/v2/foo===delete
- /**/*.html===get
- /**/*.js===get
- /**/*.css===get
- /**/*.ico===*
- /**/*.png===*


# account info
# there are three account: sam, tom, lisa
# eg: sam has [role1,role2,role3], password is sam123, has salt -> 123
# eg: tom has role2, password is tom123
# eg: lisa has role3, password is lisa123
account:
- appId: sam
# if add salt, the credential is encrypted by md5 - result is: MD5(password+salt)
# digest auth not support encrypted credential
credential: 1B9E9136628CB1B161AE47132DD7AF19
salt: 123
role: [role1,role2,role3]
- appId: tom
credential: tom123
role: [role2]
- appId: lisa
credential: lisa123
role: [role3]

0 comments on commit ab343ca

Please sign in to comment.