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

Securing Spring Cloud Microservices With OAuth2相关推荐

  1. 实战干货!Spring Cloud Gateway 整合 OAuth2.0 实现分布式统一认证授权!

    今天这篇文章介绍一下Spring Cloud Gateway整合OAuth2.0实现认证授权,涉及到的知识点有点多,有不清楚的可以看下陈某的往期文章. 文章目录如下: 微服务认证方案 微服务认证方案目 ...

  2. Spring Cloud Gateway 结合 OAuth2 提供 UAA 服务,来袭。

    微服务做用户认证和授权一直都是一个难点,随着 OAuth2.0 的密码模式被作废,更是难上加难了.今天胖哥群里的一个群友搭建用户认证授权体系的时候遇到了一些棘手的问题,这让胖哥觉得是时候分享一些思路出 ...

  3. Spring Cloud Gateway 结合OAuth2提供UAA服务

    微服务做用户认证和授权一直都是一个难点,随着OAuth2.0的密码模式被作废,更是难上加难了.今天胖哥群里的一个群友搭建用户认证授权体系的时候遇到了一些棘手的问题,这让胖哥觉得是时候分享一些思路出来了 ...

  4. Spring Cloud Security:Oauth2实现单点登录

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录功能,本文将对其单点登录用法进行详细介绍. 单点登录简介 单 ...

  5. Spring Cloud Security:Oauth2结合JWT使用

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2还可以实现更多功能,比如使用JWT令牌存储信息,刷新令牌功能,本文将对其结合 ...

  6. Spring Cloud Security:Oauth2使用入门

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录.令牌中继.令牌交换等功能,本文将对其结合Oauth2入门使 ...

  7. 带有Spring Cloud Microservices的JSON Web令牌

    在Keyhole,我们已经发布了几个有关微服务的博客 . 我们已经讨论了微服务环境中使用的架构模式,例如服务发现和断路器 . 我们甚至在平台和工具上发布了博客,例如最近关于Service Fabric ...

  8. Spring Cloud OAuth2 认证服务器

    1.Spring Cloud OAuth2介绍 Spring Cloud OAuth2 是 Spring Cloud 体系对OAuth2协议的实现,可以用来做多个微服务的统一认证(验证身份合法性)授权 ...

  9. Spring Cloud微服务网关Zuul过滤链和整合OAuth2+JWT入门实战

    一.Spring Cloud Zuul 过滤链 1.1 工作原理 Zuul的核心逻辑是由一系列的Filter来实现的,他们能够在进行HTTP请求或者相应的时候执行相关操作.Zuul Filter的主要 ...

最新文章

  1. 如何用eclipse操作MySQL数据库进行增删改查?
  2. if,elif,else的关系 input print int的用法
  3. FreeMarker 一二事 - 静态模板的使用与生成
  4. 什么是爱?[转载朋友发给我的信息]
  5. 面向对象编程 object oriented programming(OOP)(第二篇)
  6. 数据复盘《糖豆人》爆火营销过程:怎么做到以小博大?
  7. 分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(11月28日-12月4日)
  8. 【原创】【狗眼看股】【2008-4-25】干扰了节奏,改变不了趋势
  9. Vue中富文本编辑器的使用
  10. 批处理中for的参数的用法
  11. (一)通过深度学习进行COVID-19诊断
  12. 人生苦短,我用python-- Day6 面向对象
  13. linux工程常用的应用命令总结:
  14. MYSQL 数据库配置优化
  15. Windows装机必备软件
  16. 232接口针脚定义_工业RS232接口总线原理与应用方案
  17. Visual studio的中英文切换
  18. java正则判断银行卡号,验证银行卡号正则
  19. [精华] RDMA技术原理分析、主流实现对比和解析
  20. 弃用server酱 自建个人消息推送

热门文章

  1. android studio导出apk_Android 应用构建速度提升的十个小技巧
  2. ov5640帧率配置_赛博朋克2077 优化设置大全!帧数50暴涨100
  3. JVM的内存配置参数
  4. Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式
  5. 第4课 - 深入浅出处理器(续)
  6. Fragment滑动切换简单案例
  7. HDOJ 4876 ZCC loves cards
  8. JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后 1
  9. Linux安装ImageMagick与JMagick完成过程及配置
  10. C#控件前缀命名规范