I. Mode description

Authorized service

Verify the identity of third-party services, mailbox users, record and manage authentication tokens, and provide Token verification for resource servers. Scenario: Log in to a third-party website using a user’s email and access the basic information, such as the profile picture and name, of the email account.

Resource service

The third-party service obtains information after logging in to the third-party service using an email account. The information is known as resources and is used to store the data resources of the email account.

Third Party services

That is, with the help of email users’ accounts, quickly log in to the third service, eliminating the complicated registration process, which helps to quickly accumulate new users.

The interaction process

The third-party service enables users to log in to the mailbox quickly, directs users to log in to the mailbox authentication service, and returns the identity token to the third-party service. The third-party service carries the token to access the mailbox resource service and obtain some basic mailbox user information.

Ii. Project configuration management

1. Case structure

The core depends on

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

There are two core component dependencies: the OAuth2 component and the Security component.

Module partition

  • Auth-server: indicates the authorization service
  • Resource-server: indicates the resource server
  • Third-server: indicates the third service

2. Configuration description

[Authorized Services]

OAuth2 configuration

The configuration management here is the authorization process and delivery of a third party to a third party identity ClientID and password, the actual scenario is a third party by E-mail account login, first is to provide the material to the mailbox management, access email service identification, open service before docking, this model is common in the business of third-party docking.

/** * emulates third-party authorization configuration */
@EnableAuthorizationServer
@Configuration
public class AuthConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    ClientDetailsService clientDetailsService;

    /** * Resource server validates Token */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
    }
    /** * Third party client request configuration, and resource service access configuration, do not set the default access, provide the default callback address */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("third01")
                .secret(new BCryptPasswordEncoder().encode("third01"))
                .resourceIds("resource-01")
                .authorizedGrantTypes("authorization_code"."refresh_token")
                .scopes("all")
                .redirectUris("http://localhost:8082/notify.html");
    }
    /** * configure the access endpoint */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authorizationCodeServices(authorizationCodeServices()).tokenServices(tokenServices());
    }
    /** * Memory management */
    @Bean
    AuthorizationCodeServices authorizationCodeServices(a) {
        return new InMemoryAuthorizationCodeServices();
    }
    /** * Token management rule */
    @Bean
    AuthorizationServerTokenServices tokenServices(a) {
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService);
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore());
        services.setAccessTokenValiditySeconds(3600);
        services.setRefreshTokenValiditySeconds(3600*7);
        return services;
    }
    @Bean
    TokenStore tokenStore(a) {
        return newInMemoryTokenStore(); }}Copy the code

Usually need a database to store third-party information, you can go to the OAuth2 open source project, obtain the table structure into the local database, and then here into the data source loading mode, simple process management is written in the source CODE SQL statement, data source introduction.

Security configuration

/** * simulate local user configuration */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /** * Password encryption mode */
    @Bean
    public PasswordEncoder passwordEncoder(a){
        return new BCryptPasswordEncoder();
    }
    /** * Virtual users and roles in memory */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("user");
    }
    /** * form login */
    @Override
    protected void configure(HttpSecurity http) throws Exception { http.csrf().disable().formLogin(); }}Copy the code

Based on the configuration in this section, you can manage the authentication process of email users. For example, you can use the email account and password to authenticate login and determine whether authorization is valid. In this section, you can manage local email accounts and store data based on data sources.

  • Case 1: THE JWT component manages the authentication mechanism
  • Case 2: Shiro component implements user rights management
  • Case 3: Security User Security authentication process

There are several components of security authentication in the Spring framework that you can take a look at before using OAuth2.

[Resource Services]

There are three main functions: configure the Token authentication mechanism carried by the third party, that is, access authorization service authentication interface, here is the customized interface of OAuth2; ResourceId Indicates the id of the resource service. It is used to control the scope of the resource service that the third service can access. Role Role of the simulated verification user. Precise control permissions.

/** * Resource service management configuration */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    /** * Token verification */
    @Bean
    RemoteTokenServices tokenServices(a) {
        RemoteTokenServices services = new RemoteTokenServices();
        services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        services.setClientId("third01");
        services.setClientSecret("third01");
        return services;
    }
    /** * Service resource ID configuration */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("resource-01").tokenServices(tokenServices());
    }
    /** * emulated user permission rules */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/user/**").hasRole("user") .anyRequest().authenticated(); }}Copy the code

[Third-party Services]

It mainly provides simulation of two processes: request authorization service to obtain identity token; Carries the identity token to request the resource service to obtain the data. Here is how the authorization code callback interface is handled.

@Controller
public class NotifyController {

    private static final Logger LOG = LoggerFactory.getLogger(NotifyController.class);

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/notify.html")
    public String notify(String code, Model model) {
        if(code ! =null) {
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("code", code);
            map.add("client_id"."third01");
            map.add("client_secret"."third01");
            map.add("redirect_uri"."http://localhost:8082/notify.html");
            map.add("grant_type"."authorization_code");
            Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);
            String accessToken = resp.get("access_token");
            LOG.info("Identity token: {}",accessToken);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization"."Bearer " + accessToken);
            HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
            ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/user/resource", HttpMethod.GET, httpEntity, String.class);
            model.addAttribute("notifyMsg", entity.getBody());
        }
        return "notify"; }}Copy the code

Three, the test process

Through the above test process, compare the common third-party login mechanism to understand the authorization code mode of OAuth2.