I heard that wechat search “Java fish” will change strong!

This article is in Java Server, which contains my entire Series of Java articles for study or interview

(1) Preface

In the previous project, I only used SpringSecurity. Later, I found Oauth2 in the architecture of the company. Although I had no contact with it in the business, I thought I still needed to know about it, so THIS blog came into being. This blog will explain the theory and practice of Oauth2 from the concept and simple application, not involving database and other operations.

(2) What is OAuth2

OAuth (Open Authorization) is an open standard that allows users to authorize third party applications to access their information stored on another service provider without having to provide user names and passwords to third party mobile applications or share all content of their data. OAuth2.0 is a continuation of the OAuth protocol. But not backward compatible with OAuth1.0 is completely abolished OAuth1.0.

The OAuth2 protocol contains several roles: Client, Resource Owner, Authorization Server, and Resource Server.

The diagram above describes the operation principle of OAuth2 protocol in great detail:

A: The user opens A client and the client sends A request to the owner of the resource

B: The resource owner returns a result that requires authorization

C: The user initiates authorization on the client, and the authorization information is sent to the authentication server

D: The authentication server returns the token after the authentication is complete

E: The client accesses the resource server through the token

F: The resource server returns the corresponding resource,

Take a website using wechat third-party login as an example:

A: The user opens A website through the client

B: A website returns information requiring third-party login

C: The user agrees to log in on the client by scanning codes

D: The authentication server returns the token after successful login to the client

E: The client accesses the resource server with a token

F: The resource server receives the token and returns the corresponding resource

(iii) Application scenarios of OAuth2

Wechat third party is one of the application scenarios of OAuth2.

When we use wechat third-party login, we need to first apply to wechat for AppID and AppKey, and then call the authorization interface with the ID and key.

In general, most companies will use Oauth2 in a unified certification authority for third-party services to access some of their resources.

(4) Four modes of OAuth2 protocol

4.1 Authorization Code Mode authorization_code

The most common pattern, the one described above, is to obtain tokens on request and use tokens to access resources. It is more secure because it does not involve user name and password leakage.

4.2 Password Format password

The way the user name and password are passed is not secure.

Implicit

Request a token directly from the authentication system without passing an authorization code. Very few scenarios are used.

4.4 Client_credentials in Client Mode

The client obtains authorization from the authentication server in its own name. This scenario is also rare. For example, only one hardware can access a system.

(5) the realization of OAuth2 authentication server

OAuth2 is just a protocol, and Spring-Security-OAuth2 is an implementation of this protocol. Next, spring-Security-OAuth2 implements authentication and authorization.

5.1 Importing Dependencies

Start by introducing the necessary dependency packages in your project

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.1.5. RELEASE</version>
</dependency>
Copy the code

5.2 SpringSecurity configuration

Spring-security-oauth2: spring-security-oAuth2: Spring-security-oAuth2: Spring-security-oAuth2: Spring-security-oAuth2: Spring-security-oAuth2: Spring-security-oAuth2

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("root")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .authorities("/ *");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .httpBasic() .and() .csrf().disable(); }}Copy the code

The above is the basic SpringSecurity configuration class, which is logged in with the user name root and password 123456 set in memory.

5.3 OAuth Authorization Configuration

AuthorizationServer is configured as an authentication server. When the conditions passed in meet the configuration, it carries the corresponding code value in the callback interface. The following code configures a few important parameters, which have been commented out.

@Component
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter{
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
          // Enable form authentication
         security.allowFormAuthenticationForClients()
                .checkTokenAccess("permitAll()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //client_id
                .withClient("javayz")
                //secret
                .secret(bCryptPasswordEncoder.encode("my_secret"))
                // Authorization mode
                .authorizedGrantTypes("authorization_code")
                // scope, that is, scope of permission
                .scopes("all")
                // Resource ID
                .resourceIds("my_resource")
                // Callback address
                .redirectUris("http://localhost:8080/callback");
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(a){
        return newBCryptPasswordEncoder(); }}Copy the code

5.4 Method for Obtaining a Token

First step, access the authentication interface:

http://localhost:8080/oauth/authorize?client_id=javayz&response_type=code

For the first time, SpringSecurity intercepts the user name and password. In my case, since they are written in memory, I can enter root and 123456.

After entering the user name and password, OAuth will let you choose whether to authorize or not. This step can be understood as wechat scan code and click authorization on the phone when a third party logs in.

After successful authorization, it jumps to the callback interface with a code value.

http://localhost:8080/callback?code=KGNujV

Then we need to get the token with these code values:

When all parameters are filled in correctly, you get the access_token

Since we have enabled form authentication in the above code, we can use the interface to determine whether the token is valid:

(6) the realization of Oauth2 resource server

Write a resource server for authentication, create a new resource project, start the port and authentication service is different, write a resource server configuration class:

@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    private static String ClientId="javayz";
    private static String Security="my_secret";

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    / / token validation
    @Bean
    public RemoteTokenServices remoteTokenServices(a){
        RemoteTokenServices tokenServices=new RemoteTokenServices();
        tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        tokenServices.setClientId(ClientId);
        tokenServices.setClientSecret(Security);
        return tokenServices;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        http.authorizeRequests().anyRequest().authenticated();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("my_resource").stateless(true);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(a){
        return newBCryptPasswordEncoder(); }}Copy the code

The core of this code is remoteTokenServices, which needs to define the token verification address and the corresponding client and secret.

Then write an interface to test:

@RestController
public class TestController {
    @GetMapping("/test")
    public String test(a){
        return "Test interface"; }}Copy the code

Since we set authentication for all requests in the configuration class, we will be prompted with no permission when we directly access:

In this case, the tokens generated above need to be put into the authentication information in two ways. The first way is for Postman to set up Bearer tokens in the Authorization

The second way is to set authentication in the request header, paying attention to the prefix of the token

(7) Summary

From this blog post, you should know what Oauth2 is and try it out for your own projects. For use at the company level, there are other issues to consider, such as how user information is stored, how tokens are generated, and so on. I’m fish boy. See you next time!