Securing Spring Cloud Microservices With OAuth2

From Zero to OAuth2 in Spring cloud

Today I am presenting hours of research about a (apparently) simple question: “How can I maintain security in my microservices architecture?”. The task is to enable a simple but mighty possibility to secure spring cloud services down to method invocation level, having a central point of where users and authorities can be assigned.

To achieve this as efficient as possible, OAuth2 is the solution.

In this article we are going to implement an authorization server, holding user authorities and client information, and a resource service with protected resources, using Spring OAuth2 and JSON Web Tokens (JWT). I will demonstrate, how the resource server can host a RESTful resource, having different security levels, which is defined in example authorities “FOO_READ” and “FOO_WRITE”.

The implementation can be downloaded and tested on my GitHub Repository.

Since I am really new to Spring and Spring Cloud including all its concepts, this was a quite hard way of research. This might sound weird, but at the beginning I couldn’t get, why they are all talking about Facebook/GitHub authentication in context of how to secure internal data. It was leading to an obvious question:

Why OAuth2?

Despite microservices are a rather new topic in modern software development, OAuth2 is a well known authorization technology. It is widely used, to give web applications developers access to users data at Google/Facebook/GitHub directly from the foreign services in a secure way. But before I explain more details, I will first refocus, what we initially want to achieve: cloud security.

So, what could we do generally, to gain/forbid access to resources inside the cloud to users? Let’s take some dumb stupid ways.

We could secure the edge server, assuming all the access to our data will go through it. This is nearly the same as you would do with classic Spring MVC Security. But there is no way of method security and - what is the most important - your data is insecure from inside attacks.

Other way: We share the user credential database for all services and authenticate the user on each service before access. Sounds somehow really stupid, but it’s actually a working approach with all the spring security features available.

Better way: The user authenticates on a authorization service, which maps the user session to a token. Any further API call to the resource services must provide this token. The services are able to recognize the provided token and ask the authorization service, which authorities this token grants, and who is the owner of this token.

This sounds like a good solution, doesn’t it? But what’s about secure token transmission? How to distinguish between access from a user and access from another service (and this is also something we could need!)

So this leads us to: OAuth2. Accessing sensible data from Facebook/Google is pretty much the same as accessing protected data from the own backend. Since they are working for some years on this solution, we can apply this battleground approved solution for our needs.

How OAuth2 works

Implementation of OAuth2 in Spring is quite easy, when you understand the concept of OAuth2. Let us describe the scenario “AwesomeApp wants Peters profile data from facebook for Peters profile in AwesomeApp”

OAuth2 defines 4 roles in this process:

  • Resource Owner - this is Peter
  • Resource Server - this is Facebook
  • Authorization Server - this is also Facebook, because it knows Peter and its Session and data
  • Client - the AwesomeApp

When Peter tries to sign up with Facebook Login, Awesome App redirects him to FBs authorization server. This knows about Peter, whether he is logged in, and even if Peter already was here before and already approved it’s data. When Peter visits this page for the first time, he has to allow AwesomeApp to access his email and profile data. These two sources are defined as scopes, which AwesomeApp defines in Facebooks AwesomeApp Facebook-app. The developer of AwesomeApp provided to ask exactly for these two permissions.

Peter gives his permission, and is redirected to AwesomeApp with a access token. AwesomeApp then uses the access token to retrieve Peters email and profile data directly from Facebook, with no need to authenticate with Peters credentials. More than that, each time Peter signs in to AwesomeApp, he visit the authorization page again, which already knows his decision and directly responds with a token.

So far…but how to apply this on our brutal real world? In springs OAuth2 implementation as well as in all examples, they are talking about clients and scope.

Are OAuths “clients and scopes” the same as our classical “user and authorities”?

Do I have to map authorities to scopes or users to clients?

Why do I need clients?

You are maybe trying to map the roles from the first scenario to enterprise case. This is tricky!

Second scenario: Any kind of application provides user login. This login results in a exchange of user credentials to access token. All further API calls provide this token in its HTTP header. The services inside are asking the authorization server to check the token and grant access. In the other direction, the services may request data from another service, granted by authorization service using a different client with different permissions than the user, which initiated the request.

As you see, the four OAuth2 roles depend of the direction in which data is requested. For asking protected business data from resource server, the authorization server is what it is, the resource servers also, the application is the client and the service holding the permissions (often the same as authorization server), is the owner. When asking the users data, the authorization service becomes a resource server, and resource server the client.

Scopes and Roles, Clients and Users

With OAuth2 you can define, which application (web, mobile, desktop, additional website) can access which resources. So there is one dimension, where we have to decide which user can access which data, but also which application or service, can access which resource. In other words: scopes are access controlling which endpoints are visible to clients, and authorities filter the data to the user based on his permissions.

In a web shop, the frontend may act as an client, having access to products, orders and customers, but the backend also about logistics, contracts and more, independent of the users authorities. In the other way, a user may have potential access to a service but no access to all its data, because he is using a web application, where other users are permitted to access while he is not. This service-to-service access, is our other dimension. If you are familiar with math, I can say: the client-scope-relation is linear independent to the user-authority-relation in OAuth2.

Why JWT?

OAuth2 is not about, how the token is looking like and where it is stored. So one approach is, to generate random strings and save token related data to these string in a store. Over a token endpoint, other services may ask something “is this token valid, and which permissions does it grant?”. This is the “user info URL” approach, where the authorization server is turning into a resource server for the user info endpoint.

As we talking about microservices, we need a way to replicate such a token store, to make the authorization server scalable. Despite this is a tricky task, there is one more issue with user info URL. For each request against a resource microservice containing a token in the header, the service will perform another request to authorization server to check the token. So without caching tricks, we got twice more request we really need, only for security. So both, scaling token store and token request are affecting the scalability of our architecture heavily. This is where JWT (pronounced as “jot”) come into play.

In short, the answer of that user info URL request, containing info about the OAuth client, optionally the user with its authorities and the granted scope, is serialized into JSON first, encoded with base64 and finally signed using a token. The result is a so called JSON Webtoken, which we use as an access token directly. When these JWTs are signed using RSA, the authorization server first signs it with the RSA private key, assuming every resource server will have a public key. When this token is passed via HTTP header, the resource servers just have to take this JWT, verify it was really signed by the proper private key (meaning this token is coming from authorization server), and instead of asking user info, deserializing the JSON content into a OAuth2Authentication, establishing a SecurityContext based on this.

Using JWT provides a simple way of transmitting hard to fake tokens, containing the permissions and user data in the access token string. Since all the data is already inside, there neither is a need to maintain a token store, nor the resource servers must ask authorization for token checks.

So, using JWT makes OAuth2 available to microservices, without affecting the architectures scalability.

implementing the authorization service

For the later token exchange we first generate a JWT token keystore

1
keytool -genkeypair -alias jwt -keyalg RSA -dname "CN=jwt, L=Berlin, S=Berlin, C=DE" -keypass mySecretKey -keystore jwt.jks -storepass mySecretKey

Then execute

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ keytool -list -rfc --keystore jwt.jks | openssl x509 -inform pem -pubkey
Keystore-Kennwort eingeben:  mySecretKey
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwR84LFHwnK5GXErnwkmD
mPOJl4CSTtYXCqmCtlbF+5qVOosu0YsM2DsrC9O2gun6wVFKkWYiMoBSjsNMSI3Z
w5JYgh+ldHvA+MIex2QXfOZx920M1fPUiuUPgmnTFS+Z3lmK3/T6jJnmciUPY1pe
h4MXL6YzeI0q4W9xNBBeKT6FDGpduc0FC3OlXHfLbVOThKmAUpAWFDwf9/uUA//l
3PLchmV6VwTcUaaHp5W8Af/GU4lPGZbTAqOxzB9ukisPFuO1DikacPhrOQgdxtqk
LciRTa884uQnkFwSguOEUYf3ni8GNRJauIuW0rVXhMOs78pKvCKmo53M0tqeC6ul
+QIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIDGTCCAgGgAwIBAgIEOkszIDANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJE
RTEPMA0GA1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xDDAKBgNVBAMTA2p3
dDAeFw0xNjAyMDExNzQwMTlaFw0xNjA1MDExNzQwMTlaMD0xCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEMMAoGA1UEAxMDand0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwR84LFHwnK5GXErnwkmD
mPOJl4CSTtYXCqmCtlbF+5qVOosu0YsM2DsrC9O2gun6wVFKkWYiMoBSjsNMSI3Z
w5JYgh+ldHvA+MIex2QXfOZx920M1fPUiuUPgmnTFS+Z3lmK3/T6jJnmciUPY1pe
h4MXL6YzeI0q4W9xNBBeKT6FDGpduc0FC3OlXHfLbVOThKmAUpAWFDwf9/uUA//l
3PLchmV6VwTcUaaHp5W8Af/GU4lPGZbTAqOxzB9ukisPFuO1DikacPhrOQgdxtqk
LciRTa884uQnkFwSguOEUYf3ni8GNRJauIuW0rVXhMOs78pKvCKmo53M0tqeC6ul
+QIDAQABoyEwHzAdBgNVHQ4EFgQUxebRVICNPg65T2RgrOe2J5qDMXMwDQYJKoZI
hvcNAQELBQADggEBAAHBF3JQ2ZsEjuYYwU5cp9BzBJoTQyChF37AA76EorrcSeqo
Rui1dUIfXbImIOZ5PBNk34IFWROTwpw80zBCZQ7NQ81ITzuhsxjbX7Wxj6iCq3u9
TDN+IxiaZMvJ2PDfeRqr93HOwMTMttxyW4KVa3geQ+yMMSZrxagEpqMA1Fviqa6T
5u8DNqfXQ8Hg+yG2bMNQs6GleAFkRprkHjR6yY7ehmIVMZ7iBkkXh8IO8fKy2WNK
uWa+DO2lXJj1W7HLXeaeT0twAqwyoNj2/pxMuv/JrTlNkhcUTmP+UBAJZih0KSGD
9TSKs5HlBGsIUpILuauNzZk1VS2RCyVtD1zf7vM=
-----END CERTIFICATE-----

You will be prompted to enter your secret key. Copy the public key (including the dashed lines) into a file named “public.cert”.

Copy this file to src/main/resources.

the plan

In this example we will define a resource “foo”, which can be read with authority FOO_READ and can be written with FOO_WRITE.

On the authentication service we have the user “reader”, who can read a foo, and a “writer”. To make the resource server accessible by a web application, we define a “web_app” client.

First we define our gradle file. Use start.spring.io to generate a gradle boot application with “Web” dependency.

this gradle file will be used for resource server also!

Now we adjust the dependencies to this

1
2
3
4
5
6
dependencies {
  //...
  compile('org.springframework.security.oauth:spring-security-oauth2')
  compile('org.springframework.security:spring-security-jwt')
  //..
}

To make the configuration non-confusing, I will use separate configurations instead of mixing all in inside the Application class. In both examples they are as they roll out from spring initialzr.

OAuth2Configuration

We begin with the following configuration

1
2
3
4
5
@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
    //..
}

To define a default spring configuration, and enable the current application as an OAuth2 authorization server.

We inherit the class from AuthorizationServerConfigurerAdapter, to configure the details.

src/main/java/package/config/OAuth2Configuration.java

1
2
3
4
5
6
7
8
9
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("web_app")
                .scopes("FOO")
                .autoApprove(true)
                .authorities("FOO_READ", "FOO_WRITE")
                .authorizedGrantTypes("implicit","refresh_token", "password", "authorization_code");
    }

We assume FOO as resource access identity (so we can check this with #oauth2.hasScope(‘FOO’) to apply client access permission), auto approve for the scope for code authorization and pass the authorities for resource server.

Now we configure the OAuth2 endpoints to adjust the authentication manager (which will represent the web-security users), and JWT token store configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.tokenStore(tokenStore()).tokenEnhancer(jwtTokenEnhancer()).authenticationManager(authenticationManager);
}

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;

@Bean
public TokenStore tokenStore() {
    return new JwtTokenStore(jwtTokenEnhancer());
}

@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
    KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "mySecretKey".toCharArray());
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setKeyPair(keyStoreKeyFactory.getKeyPair("jwt"));
    return converter;
}

We define another configuration for the web security.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Bean
    public AuthenticationManager    authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and()
                .authorizeRequests()
                .antMatchers("/**").authenticated()
            .and()
                .httpBasic();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("reader")
                .password("reader")
                .authorities("FOO_READ")
                .and()
                .withUser("writer")
                .password("writer")
                .authorities("FOO_READ", "FOO_WRITE");
    }
}

Note that there is no “@EnableWebSecurity”, because it’s automatically applied through @EnableAuthorizationServer. We also declare the authenticationManagerBean as a bean, which will be injected in the OAuth configuration above. HttpSecurity and user definition is quite straight forward, and can be implemented in various ways like UserDetailsService.

We configure the application to run on port 9999 for now.

indepth: we are using OAuth2 as authentication protocol, too. This approach is similar to OpenID connect, which is also a standard authentication protocol over OAuth2, more relying to public identity providers, such as Google, GitHub etc.

get access tokens

I will show how to get access token directly via username/password. There are other authorization types such as authorization code, implicit, client credentials.

To get a token, just

1
2
$ curl -XPOST "web_app:@localhost:9999/oauth/token" -d "grant_type=password&username=reader&password=reader"
{"access_token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0NTQ0MDA3MzQsInVzZXJfbmFtZSI6InJlYWRlciIsImF1dGhvcml0aWVzIjpbIkZPT19SRUFEIl0sImp0aSI6IjU1MWI4MTY4LTMwZmItNDZlNS1iMzJlLTc4ODRjNjJlNzZlYiIsImNsaWVudF9pZCI6IndlYl9hcHAiLCJzY29wZSI6WyJGT08iXX0.cKcgkLcbBECSWlz5fllb5V0EkfvrIq6RxjId34mNvhifS5bseQD5c8SlsQ_MvLf6unmosIHT_WL9TP56UUPX5TFrQpT09c2RPvnyhKD5PLlrf9o2RAAL5xS1yQqAWoSoNlx73m8cs8xOjIEix3mthNzEDlLYgsBbQci0ZWBCQHwnRE3OW4oykm4YH5X59X-8Juq1enztbdcjcyt4aFQOG7KVstW5M0MN3y3MMD4O9QgsatzBWDL2lPoazhKuYkR9LcoBZrKF_WzQgwolMhK_ousOxLEHNbKoWxOWJPJnayi6NW8o_2SlkTs7ykDh_GEGOSswpMGhkw98DI5dwFcTQg","token_type":"bearer","refresh_token":"eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJyZWFkZXIiLCJzY29wZSI6WyJGT08iXSwiYXRpIjoiNTUxYjgxNjgtMzBmYi00NmU1LWIzMmUtNzg4NGM2MmU3NmViIiwiZXhwIjoxNDU2OTQ5NTM0LCJhdXRob3JpdGllcyI6WyJGT09fUkVBRCJdLCJqdGkiOiI0MTBlZWNjMS01NTRiLTQ0OGQtOGUyOC1iMGE3NTg5N2JlNzMiLCJjbGllbnRfaWQiOiJ3ZWJfYXBwIn0.Rw5ASYQjsJtPfWMMNIQ1TQA53VAqMSoDze8RHzbdRgXkn_BS-Qc84rTNg5deICL_Qdz6D3OtRL2pXgAkOn6ImCDJGaKcroZscZ1Mpy7lmBbsBf1pOolqOsXbCItOPh7h8CpB41ZipTeq-v_-5LQ7wNqwMTOzW_zL8On7bc0ZLF66PY-HK8BlFYUaiJRdJqP1PjfCh8hmOUMYnX8slQcdVMP4V1m6ZzdVFuhywKi3LD6tzrU-q1s2FEUVIpOCKJ6pKv9ts6tSK_lcjLjFO0rRzjTSdtywKE5Gc1rvC4BJALN_ZOn_uiskzo8IIztDUefZJV5OCAZ41igDUXbJHb1NSA","expires_in":43199,"scope":"FOO","jti":"551b8168-30fb-46e5-b32e-7884c62e76eb"}

implementing the resource server

We generate another Spring Boot application with Web starter and take the same gradle dependencies we used for the authorization server before. Copy the public.cert file into src/main/resources.

First, we have to implement the resource itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("/foo")
public class WebController {

    @GetMapping
    public String readFoo() {
        return "read foo " + UUID.randomUUID().toString();
    }

    @PostMapping
    public String writeFoo() {
        return "write foo " + UUID.randomUUID().toString();
    }
}

This is a simple controller. I use UUID random strings to be sure every response will be unique (for cache things).

Since we use JWT tokens, we have to configure the token store and token converter for JWT.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Configuration
public class JwtConfiguration {
    @Autowired
    JwtAccessTokenConverter jwtAccessTokenConverter;

    @Bean
    @Qualifier("tokenStore")
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        JwtAccessTokenConverter converter =  new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.cert");
        String publicKey = null;
        try {
            publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        return converter;
    }
}

Now lets configure the resource server security:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/**").authenticated()
                .antMatchers(HttpMethod.GET, "/foo").hasAuthority("FOO_READ");
                //.antMatchers(HttpMethod.POST, "/foo").hasAuthority("FOO_WRITE");
                //you can implement it like this, but I show method invocation security on write
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("foo").tokenStore(tokenStore);
    }

    @Autowired
    TokenStore tokenStore;

    @Autowired
    JwtAccessTokenConverter tokenConverter;
}

Note I commented the access rule for write requests on foo. I will show how to secure this via method invocation level security.

adding method security

To enable method security we just create a configuration like this:

1
2
3
4
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class GlobalMethodSecurityConfiguration {
}

and change the writeFoo method in our rest controller:

1
2
3
4
5
@PreAuthorize("hasAuthority('FOO_WRITE')")
@PostMapping
public String writeFoo() {
    return "write foo " + UUID.randomUUID().toString();
}

You may ask why I didn’t use “secureEnabled = true” and the @Secured annotation. Sadly, this doesn’t work at the moment.

We run this application on port 9090.

testing

Now copy the access token from our last curl command and create a local variable TOKEN:

1
$ TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0NTQ0MDA3MzQsInVzZXJfbmFtZSI6InJlYWRlciIsImF1dGhvcml0aWVzIjpbIkZPT19SRUFEIl0sImp0aSI6IjU1MWI4MTY4LTMwZmItNDZlNS1iMzJlLTc4ODRjNjJlNzZlYiIsImNsaWVudF9pZCI6IndlYl9hcHAiLCJzY29wZSI6WyJGT08iXX0.cKcgkLcbBECSWlz5fllb5V0EkfvrIq6RxjId34mNvhifS5bseQD5c8SlsQ_MvLf6unmosIHT_WL9TP56UUPX5TFrQpT09c2RPvnyhKD5PLlrf9o2RAAL5xS1yQqAWoSoNlx73m8cs8xOjIEix3mthNzEDlLYgsBbQci0ZWBCQHwnRE3OW4oykm4YH5X59X-8Juq1enztbdcjcyt4aFQOG7KVstW5M0MN3y3MMD4O9QgsatzBWDL2lPoazhKuYkR9LcoBZrKF_WzQgwolMhK_ousOxLEHNbKoWxOWJPJnayi6NW8o_2SlkTs7ykDh_GEGOSswpMGhkw98DI5dwFcTQg

and peform a call to read the foo resource

1
$ curl -H "Authorization: Bearer $TOKEN" "localhost:9090/foo"

and you should get a positive result, while

1
$ curl -XPOST -H "Authorization: Bearer $TOKEN" "localhost:9090/foo"

should result in access denied. To get access to write on foo, we must get a token as “writer”.

Conclusion

This should be a very brief introduction into how you can use OAuth2 in spring cloud microservices. If I explained something wrong, please be free to correct me. I am open to any kind of critics :)

The most important is, this sample works so you can try it out and change it in a way you need. May someone find this article useful :)

More resources

  • JHipster UAA docs for using a working setup using this basics to secure spring cloud microservices
  • JHiosoter UAA demo setup: a set of several JHipster microservices, demonstrating both user-to-service (Angular client) and service-to-service authorization (Feign Clients)

Have a great week.

http://stytex.de/blog/2016/02/01/spring-cloud-security-with-oauth2/

https://github.com/xetys/spring-cloud-oauth2-example

时间: 2024-09-11 15:56:34

Securing Spring Cloud Microservices With OAuth2的相关文章

Service Tracing Analysis on Spring Cloud Applications Using Zipkin

This article briefly introduces how to use Zipkin to perform service analysis on Spring Cloud applications. In practical application, Zipkin can be used in combination with stress testing tools to analyze the availability and performance of systems u

使用Spring Cloud和Docker构建微服务

本文讲的是使用Spring Cloud和Docker构建微服务,[编者的话]这是系列博文中的第一篇,本文作者使用Spring Cloud和Docker构建微服务平台,文章的例子浅显易懂. 本系列博文主要向大家介绍如何使用Spring Cloud和Docker构建微服务平台. 什么是Spring Cloud? Spring Cloud 是Pivotal提供的用于简化分布式系统构建的工具集.Spring Cloud引入了云平台连接器(Cloud Connector)和服务连接器(Service Co

Spring Cloud系列(1)Spring Cloud概述

本站小福利 点我获取阿里云优惠券 原文作者:杨大仙的程序空间 1 Spring Cloud概述         本文要点              传统应用的问题              微服务与Spring Cloud              本书介绍         本章将会简述Spring Cloud的功能,描述什么是Spring Cloud,它能为我们带来什么,为后面学习该框架的知识打下理论的基础. 1.1 传统的应用 1.1.1 单体应用         在此之前,笔者所在公

搭建spring cloud微服务架构

在搭建环境之前,首先根据公司的业务定义微服务架构的代码结构,因为考虑到不同行业,不同领域,不同业务,我这边针对于所有行业做通用的架构模式. 项目整个架构使用maven来构建的,使用maven不仅仅是jar包的管控,重要的是要抓住maven的一个核心作用,那就是将整个项目按照模块化的方式进行划分,业务与业务之间解耦,然后将模块化的业务再进行服务化或者组件化,这样可以进行任意的项目或者平台的业务移植. 最后还要考虑到服务的细粒度拆分,比如:一个登录的模块,我们可以将所有跟登录有关系的业务进行服务化(

Spring Cloud Security

Spring Cloud and OAuth2 官方文档Github实例

服务网关 Spring Cloud Zuul

(git上的源码:https://gitee.com/rain7564/spring_microservices_study/tree/master/fifth-spring-cloud-zuul) 对于服务网关是什么.有什么用?使用API Gateway这篇文章已经讲得很清楚了,这里就不再赘述.当然这只是翻译版,原版在这里:Building Microservices: Using an API Gateway Spring Cloud和Netflix Zuul Using an API Ga

Spring Cloud微服务升级总结

一.应用系统的架构历史 [ 二.什么是微服务? 2.1 微服务概述 起源:微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇文章"Microservices".文中内容提到:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值. 通信方式:每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API). 微服务的常规定义:微服务是一种架构风

阿里Dubbo疯狂更新,关Spring Cloud什么事?

最近,开源社区发生了一件大事,那个全国 Java 开发者使用最广的开源服务框架 Dubbo 低调重启维护,并且 3 个月连续发布了 4 个维护版本. 我上次在写放弃Dubbo,选择最流行的Spring Cloud微服务架构实践与经验总结这篇文章的时候,就有很多的网友给我留言说,Dubbo 又开始更新了.我当然是清楚的,我也一直在关注着 Dubbo 的走向,在几个月前技术圈里面就有一个消息说是 Dubbo 又开始更新了,大家议论纷纷不知真伪.我还专门跑到 GitHub 上面进行了留言询问,最后在

Spring Cloud 接入 EDAS 之全链路跟踪

在上一篇 Spring Cloud 接入 EDAS 之服务发现篇 中已经讲解了如何接入 EDAS 的服务注册中心.在这一篇中,我们将聊聊全链路跟踪. 全链路跟踪的必要性 微服务框架带来的好处已经无需多言,模块化,解耦,提高了开发的效率,服务具备更好的扩展性等等.但是微服务其实是一把双刃剑,微服务同时也带来了一些问题. 随着业务的拆分越来越细,模块越来越多,一个看似简单的业务动作,很可能跨越了几十个系统,调用链非常复杂. 基于微服务体系之下构建的业务系统存在的问题基本上分为四类. 故障定位难 即使