Foreword
In Spring Cloud Advanced Road | Seven: Serving Gateway (zuul) article, has elaborated on the role and importance of the gateway, which can not only route forward and request filtering, you can also check the permissions, auditing, interfaces monitoring, current limit, and the like log collection logic.
To accomplish these additional logic required to integrate other frame, or the development of appropriate filter, but also the code or logic. This paper focuses on integrated security framework, for example, demonstrates how to authenticate the gateway.
As mentioned above, the micro-service architecture, to a large single applications and services split into several or even dozens of micro-support services, in order to ensure high availability, each micro-services are likely to be deployed cluster.
According to previous article Spring Cloud Advanced Road | Eight: Authorized Service (Spring Cloud Oauth2) , Spring Cloud Advanced Road | nine: Resource Service (Spring Cloud Oauth2) single service after the exposition, server resources are split, provide resources services.
Since it is outside resources to provide services, it is bound to cause a problem, namely security issues. At this time, there will be two options: the discretion of each resource services, unified by the gateway process, each resource services focus only on business.
If each resource services handle, micro service after the split, each service logic required to handle the same security, workload serious repeat. Even extract the public part, can not solve the big problem. Because the public portion only solve the authentication problem, not solve the authentication service for each resource rights are different.
Unified by the gateway handles, the gateway itself as a resource service, the initial direct authentication, then authentication through the authentication after, are proceeding to the next logical after the adoption. In this case, each resource service only concerned about their own business, without having to deal with cumbersome security policies.
As for the rights issue, the rights to develop a unified support platform, unified management of all the resources and services of the user permissions, resource line is automatically registered on the service platform to support permissions, and then by the uniform distribution to maintenance personnel.
Ready to work
Prior to reuse articles Spring Cloud Advanced Road | Seven: Serving Gateway (Zuul) , Spring Cloud Advanced Road | Eight: Authorized Service (Spring Cloud Oauth2) , Spring Cloud Advanced Road | nine: Resource Service (Spring Cloud oauth2) project.
Transformation xmall-product
Earlier, according to each resource service no longer exists as an authorized service resources services relative , therefore, need to remove the Spring Cloud Oauth2 related content.
Delete Spring Cloud Oauth2 dependent
pom file modified as follows.
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.luas.cloud</groupId>
<artifactId>java-boot-parent-2.1</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../java-boot-parent-2.1</relativePath>
</parent>
<groupId>com.luas.cloud</groupId>
<artifactId>xmall-product</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>xmall-product</name>
<description>Spring Cloud Learning,nacos-client</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos cloud -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Delete oauth2 resources
Delete application.yml in oauth2 resource configuration information, delete as follows.
server:
port: 8080
Delete ResourceServer configuration
Such as starting class has @EnableResourceServer notes, it is deleted.
package com.luas.xmall;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class XmallProductApplication {
public static void main(String[] args) {
SpringApplication.run(XmallProductApplication.class, args);
}
}
As ResourceServerConfiguration configuration class exists, it deletes.
package com.luas.xmall.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.anyRequest()
.and()
.authorizeRequests()
.antMatchers("/application").permitAll()
.anyRequest()
.authenticated();
}
}
Reconstruction Gateway
Add Spring Cloud Oauth2 dependent
Add spring-cloud-starter-oauth2 dependent, pom modified file as follows.
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.luas.cloud</groupId>
<artifactId>java-boot-parent-2.1</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../java-boot-parent-2.1</relativePath>
</parent>
<groupId>com.luas.xmall</groupId>
<artifactId>xmall-zuul</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>xmall-zuul</name>
<description>网关服务</description>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!-- nacos cloud -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Modify the application configuration
Add authorization server routing rules, oauth2 allocation of resources .
server:
port: 5566
zuul:
prefix: /gateway
sensitive-headers:
routes:
auth:
path: /auth/**
service-id: xmall-auth
strip-prefix: true
product:
path: /product/**
service-id: xmall-product
strip-prefix: true
security:
oauth2:
resource:
user-info-uri: http://localhost:7777/oauth/user
prefer-token-info: false
Add ResourceServerConfiguration configuration class
Here there is a point, the more important: Why do not you add annotations directly @EnableResourceServer startup class open resource services, and to define the special resource services configuration?
The reason is that the default resource server security policy, the request required authentication, then get token, token verification, token key endpoints without the need to obtain these and other identity authentication to access, will be blocked. Therefore, the definition of special needs resource services security policy, the public release of these endpoints .
ResourceServerConfiguration classes are as follows.
package com.luas.xmall.gateway.configuration;
import com.luas.xmall.gateway.filter.PreAuthenticationFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.anyRequest()
.and()
.authorizeRequests()
.antMatchers("/application").permitAll()
// 放开token授权、token key获取、token验证端点
.antMatchers(PreAuthenticationFilter.TOKEN_ENDPOINT).permitAll()
.antMatchers(PreAuthenticationFilter.TOKEN_KEY_ENDPOINT).permitAll()
.antMatchers(PreAuthenticationFilter.CHECK_TOKEN_ENDPOINT).permitAll()
.anyRequest()
.authenticated();
}
}
Transformation PreAuthenticationFilter
With ResourceServerConfiguration, pre-security check also need to be open public endpoints . Further, this filter may intercept related rights, like the user information analyzing and transmission logic. As for the other, such as the audit interfaces, a filter may be to create a separate process, however, note the order of execution and a filter type .
package com.luas.xmall.gateway.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor;
import org.springframework.security.oauth2.provider.authentication.TokenExtractor;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
@Component
public class PreAuthenticationFilter extends ZuulFilter {
public static final String TOKEN_ENDPOINT = "/gateway/auth/oauth/token";
public static final String TOKEN_KEY_ENDPOINT = "/gateway/auth/oauth/token_key";
public static final String CHECK_TOKEN_ENDPOINT = "/gateway/auth/oauth/check_token";
private Logger logger = LoggerFactory.getLogger(getClass());
private TokenExtractor tokenExtractor = new BearerTokenExtractor();
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String requestURI = request.getRequestURI();
return !(requestURI.equals(TOKEN_ENDPOINT) && requestURI.equals(TOKEN_KEY_ENDPOINT) && requestURI.equals(CHECK_TOKEN_ENDPOINT));
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (this.logger.isDebugEnabled()) {
this.logger.debug("uri {}", request.getRequestURI());
}
Authentication authentication = this.tokenExtractor.extract(request);
if (authentication == null || authentication.getPrincipal() == null) {
//不会继续往下执行 不会调用服务接口了 网关直接响应给客户了
requestContext.setSendZuulResponse(false);
requestContext.setResponseBody("Full authentication is required to access this resource");
requestContext.setResponseStatusCode(401);
return null;
}
String accessToken = (String) authentication.getPrincipal();
this.logger.info("token {}", accessToken);
// todo 解析token,调用权限支撑平台,获取权限信息,组织到用户信息中传递给下游微服务
return null;
}
}
verification
In turn starts xmall-auth, xmall-product, xmall-zuul, respectively 7777,8080,5566 port.
First Direct access http: // localhost: 8080 / sku / 1122, can be a normal visit.
Go to http gateway: // localhost: 5566 / gateway / product / sku / 1122, has been unable to find a normal visit, you need to be authenticated.
Gateway service by calling authorization, authorization, address:
http://localhost:5566/gateway/auth/oauth/token?client_id=client_1&client_secret=123456&username=user_1&password=123456&scope=server&grant_type=password。
After requesting a normal return authorization result.
At this point, indicating successful transformation gateway, has played the role of server resources properly authorized for the requested resource federation server for authentication.
header way to carry authorization, re-visit http: // localhost: 8080 / sku / 1122, can be a normal visit.
网关整合安全框架以在网关进行身份认证完成,其它功能如日志收集、接口审计、鉴权等,读者可自行去参整合实现。后续也会出相关文章,对部分功能进行整合说明。
源码
github
https://github.com/liuminglei/SpringCloudLearning/tree/master/10/
gitee
https://gitee.com/xbd521/SpringCloudLearning/tree/master/10/
微信搜索【银河架构师】,发现更多精彩内容。