[note] outh2 first acquaintance

Posted by farel on Fri, 31 Dec 2021 07:56:30 +0100

SpringSecurity+oauth2.0

Study notes springsecurity+jwt+oauth2.0 getting started to mastering video tutorial [free learning] _beepbeep _bilibili bili

Personally, the content is not detailed enough, but it is suitable for entry-level learning. jwt content does not seem to reflect

1. How does the microservice interface implement authority authentication

Spring Security is a security framework that can provide declarative security access control solutions for spring based enterprise applications. It provides a set of beans that can be configured in the spring application context, and makes full use of Spring IoC, DI (inversion of control, DI: dependency injection) and AOP (aspect oriented programming) functions to provide declarative security access control function for the application system and reduce the work of writing a large amount of repeated code for enterprise system security control.

2. SpringSecurityBasic/from mode

Implement Basic authentication

Basic authentication is a relatively simple HTTP authentication method. The client transmits the user name and password to the server through plaintext (Base64 encoding format) for authentication. It usually needs to cooperate with HTTPS to ensure the security of information transmission.

Maven dependency

<dependencies>
    <!--  springboot integration web assembly-->
    <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>
</dependencies>

Configuration class

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * New authorized account
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * Adding an account mayikt password is also for mayikt to allow access to all requests
         */
        auth.inMemoryAuthentication().withUser("mayikt").password("mayikt").authorities("/");
    }

    /**
     * Add HttpSecurity configuration
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * Block http security authentication mode and set it to httpBasic mode
         */
        http.authorizeRequests().antMatchers("/**").fullyAuthenticated()
                .and().httpBasic();
    }
    // Cipher encryptor
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
}

form mode

The Form form mode is suitable for the traditional mode. The front end and back end of the project are developed in java. The initial shell is the Form form

Now it is the front and rear end separation mode, so I'll pass by

Cookies are used to store content by default.

3. Spring security implements permission control

In the enterprise management system platform, it will be split into n different accounts,

Each account corresponds to different interface access rights,

such as

Account mayikt_ All interfaces of admin can be accessed;

mayikt_ The add account can only access the / addMember interface;

mayikt_ The show account can only access the / showMember interface;

mayikt_ The Del account can only access the / delMember interface;

Related configuration

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * New authorized account
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 1.New mayikt_admin mayikt_admin permission can access all requests
         */
        auth.inMemoryAuthentication()
            .withUser("mayikt_admin")
            .password("mayikt_admin")
            .authorities("addMember", "delMember", "updateMember", "showMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_add")
            .password("mayikt_add")
            .authorities("addMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_del")
            .password("mayikt_del")
            .authorities("delMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_update")
            .password("mayikt_update")
            .authorities("updateMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_show")
            .password("mayikt_show")
            .authorities("showMember");
    }

    /**
     * Add HttpSecurity configuration
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        /**
//         * Block http security authentication mode and set it to httpBasic mode
//         */
//        http.authorizeRequests().antMatchers("/**").fullyAuthenticated()
//                .and().httpBasic();
        /**
         * Intercept http security authentication mode set to formLogin mode
         */
//        http.authorizeRequests().antMatchers("/**").fullyAuthenticated()
//                .and().formLogin();

        http.authorizeRequests()
            .antMatchers("/addMember").hasAnyAuthority("addMember")
            .antMatchers("/delMember").hasAnyAuthority("delMember")
            .antMatchers("/updateMember").hasAnyAuthority("updateMember")
            .antMatchers("/showMember").hasAnyAuthority("showMember")
            .antMatchers("/**").fullyAuthenticated().and().formLogin();
    }

    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
}

Modify page 403

Custom error exception

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

/**
 * Custom SpringBoot error exception
 */
@Configuration
public class WebServerAutoConfiguration {
    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
        ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
        ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
        ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
        factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
        return factory;
    }
}

Interface

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ErrorController {
    @RequestMapping("/error/403")
    public String error() {
        return "You currently have insufficient access to the interface!";
    }
}

Modify form mode login page

package com.mayikt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.stereotype.Component;

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
        /**
     * New authorized account
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 1.Add mayikt_admin mayikt_admin permission can access all requests
         */
        auth.inMemoryAuthentication()
            .withUser("mayikt_admin")
            .password("mayikt_admin")
            .authorities("addMember", "delMember", "updateMember", "showMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_add")
            .password("mayikt_add")
            .authorities("addMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_del")
            .password("mayikt_del")
            .authorities("delMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_update")
            .password("mayikt_update")
            .authorities("updateMember");
        auth.inMemoryAuthentication()
            .withUser("mayikt_show")
            .password("mayikt_show")
            .authorities("showMember");
    }
     @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/addMember").hasAnyAuthority("addMember")
            .antMatchers("/delMember").hasAnyAuthority("delMember")
            .antMatchers("/updateMember").hasAnyAuthority("updateMember")
            .antMatchers("/showMember").hasAnyAuthority("showMember")
            //.antMatchers("/**").fullyAuthenticated().and().formLogin()
            //And close the csrf setting, jump to the custom login page, and release the permission
        	.antMatchers("/login").permitAll()
       		.antMatchers("/**").fullyAuthenticated().and().formLogin()
            .loginPage("/login").and().csrf().disable();
    }
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
}

Custom page interface

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login() {
        return "login";
    }
}

Custom page

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Insert title here</title>
</head>
<body>

<h1>Access control login system</h1>
<form action="/login" method="post">
    <span>User name</span><input type="text" name="username"/> <br>
    <span>User password</span><input type="password" name="password"/> <br>
    <input type="submit" value="land">
</form>
<#if RequestParameters['error']??>
    Wrong user name or password
</#if>
</body>
</html>

application.yml

spring:
  freemarker:
    settings:
      classic_compatible: true #Processing null values
      datetime_format: yyy-MM-dd HH:mm
      number_format: 0.##
    suffix: .ftl
    template-loader-path:
      - classpath:/templates 

rely on

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

4. Design of RBAC permission model for spring security integration

Rbac authority table design

The core of RBAC (role-based permission control) model is to introduce the concept of role between user and permission. The direct association between user and permission is cancelled, and the user permission is indirectly given through the method of user association role and role Association permission (as shown in the figure below), so as to achieve the purpose of decoupling user and permission.

  1. Permission table
    Permission id 1 /addMember tag = addMember
    Permission id 2 /updateMember tag = updateMember
  2. Role table
    Role id 1 admin
    Role id 2 adder
  3. Role permission table
    //admin (permission tag = addMember, updateMember)
    admin - permission 1
    admin - permission 2
  4. User table
    huangdi user
    huangdou user
  5. User role table
    User - role id
    huangdou — admin, adder

The above implements the many to many correspondence

Dynamic query authority according to account name

rely on

<!-- springboot integration mybatis frame -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- alibaba of druid Database connection pool -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.9</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Configuration file dev

spring:    
	datasource:
      name: test
      url: jdbc:mysql://127.0.0.1:3306/mayikt_rbac
      username: root
      password: root
      # druid connection pool
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.jdbc.Driver

mapper interface

public interface PermissionMapper {

    @Select(" select * from sys_permission ")
    List<PermissionEntity> findAllPermission();

}
public interface UserMapper {
    /**
     * Query by user name
     *
     * @param userName
     * @return
     */
    @Select(" select * from sys_user where username = #{userName}")
    UserEntity findByUsername(@Param("userName") String userName);

    /**
     * Query user permissions
     *
     * @param userName
     * @return
     */
    @Select(" select permission.* from sys_user user" 
            + " inner join sys_user_role user_role"
            + " on user.id = user_role.user_id inner join "
            + "sys_role_permission role_permission on user_role.role_id = role_permission.role_id "
            + " inner join sys_permission permission on role_permission.perm_id = permission.id where user.username = #{userName};")
    List<PermissionEntity> findPermissionByUsername(@Param("userName") String userName);
}

Service

@Component
@Slf4j
public class MemberDetailsService implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        // 1. Query user by user name
        UserEntity userDetails = userMapper.findByUsername(userName);
        if (userDetails == null) {
            return null;
        }
        // 2. Query the corresponding permissions of the user
        List<PermissionEntity> permissionList = userMapper.findPermissionByUsername(userName);
        ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        permissionList.forEach((a) -> {
            grantedAuthorities.add(new SimpleGrantedAuthority(a.getPermTag()));
        });
        log.info(">>permissionList:{}<<",permissionList);
        // Set permissions
        userDetails.setAuthorities(grantedAuthorities);
        return userDetails;
    }
}

WebSecurity configuration

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MemberDetailsService memberDetailsService;
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(memberDetailsService).passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                String rawPass = MD5Util.encode((String) rawPassword);
                boolean result = rawPass.equals(encodedPassword);
                return result;
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
		// You need to query all permissions
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
        // Directly construct the object for each operation
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
                authorizeRequests = http.authorizeRequests();
        allPermission.forEach((p) -> {
            authorizeRequests.antMatchers(p.getUrl()).hasAnyAuthority(p.getPermTag());
        });
        
        // Set custom login page
        //And close the csrf setting, jump to the custom login page, and release the permission
        .antMatchers("/login").permitAll()
            .antMatchers("/**").fullyAuthenticated().and().formLogin()
            .loginPage("/login").and().csrf().disable();

    }

    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
}



5. How does springsecurity integrate the front and back end separation mode

6. What is Oauth2 + jwt

What is Oauth

OAuth 2.0 is an authorization protocol that allows software applications to access the resources of the resource owner on behalf of (rather than as) the resource owner. The application requests authorization from the resource owner, then obtains a token and uses it to access the resources, and the resource owner does not need to provide sensitive data such as user name and password to the application.

Oauth role division

  1. Resource Server: resources that are authorized to access
  2. Authentication server: OAUTH2 authentication and authorization center
  3. Resource Owner: user
  4. Client: partner using API

Oauth application scenario

  1. Third party federated login
  2. Open interface

Oauth integration

There is an open interface that will be called by other companies or customers, so it is necessary to design an open interface platform

For example, using wechat login is Tencent's open wechat login interface

  1. Apply for appid and password
    appidqq account - unchanged for life
    appwd = change qq password
  2. Get token with appid and password
  3. Using token to call interface
  4. The token is temporarily unique. If it fails, log in again

WeChat official account

WeChat official account test platform: https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=1820792496&lang=zh_CN , get appid and secret

appid:wxe29c41ca0bafdf4d

appsecret:a695733a9637e1d677a4f3b916c3df9b, which is used to generate the connection below

redirect_urt fill in the callback page

scope is generated by user selection, such as snsapi_base and snsapi_userinfo

  1. Generate WeChat official account authorization link: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe29c41ca0bafdf4d&redirect_uri=http://127.0.0.1:2000&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
  2. When you click confirm, authorization will redirect to http://127.0.0.1:2000?code= Authorization code. Authorization code can only be used once
    Authorization code: http://127.0.0.1:2000/?code=021I6Bll2o6Gv74In3ml2epfQv0I6BlY&state=STATE
  3. Obtain the access token according to the authorization code - valid for 2 hours
    After obtaining the code, request the following link to obtain access_ token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxe29c41ca0bafdf4d&secret=a695733a9637e1d677a4f3b916c3df9b&code=021I6Bll2o6Gv74In3ml2epfQv0I6BlY&grant_type=authorization_code
  4. Getting the {"access is the way to get the {access' '' '' '' '' '' '' ''To take a token to get the {" to get the {"to get the {" access to the access to the {"to get to the {" to get to the {"to get to the {" to get to the {"to get to the {" to get to the {"47 _099999999fmfffffffx88cpp8cp41thecost of being a full of the same time at the same time of the same time to get to get to the point of the same same thing in the same 9-9-0-g0v99mfvv8sidesidesidesidesidesidesidesidesidesidesidesidesideside7sy7sy7sythythythythythy7syt7syt7sytytytytytytytytytyt7syt7syt7sytfn-tfn-ftftftftftft" om2cg50_kZDi11gBotc1hoej6uik "," scope ":" snsapi_userinfo "}
    openid is the only id that users pay attention to official account number.
  5. User information can be obtained according to accesstoken + openid
    https://api.weixin.qq.com/sns/userinfo?access_token=47_0iZ9fCMfX8Cp41tTEFFrVGiuNm9-G0VQjlkMFv8SIR4yudKx7SYTfn-tFTXhA_iP1Fv0lXl-wwy6vf5lRB4eGQ&openid=om2cg50_kZDi11gBotc1hoej6uik&lang=zh_CN

7. Spring security integrates Oauth2 + jwt

Oauth2 pattern classification

  1. Authorization code mode
  2. Simplified mode
  3. Password mode
  4. Client mode

Authorization code mode

  1. appid and app password are required
  2. Configure callback address
  3. Validate token interface

But all of the above are integrated

Integration code maven dependency

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>
<dependencies>
    <!-- SpringBoot integration Web assembly -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!-- springboot integration freemarker -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>

    <!-->spring-boot integration security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- Spring Security OAuth2 -->
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.6.0</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

Configuration class

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Authentication account mayikt is required
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("mayikt")
            .password(passwordEncoder().encode("mayikt"))
            .authorities("/*");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated() //All requests need to be authenticated
                .and()
                .httpBasic() //Basic login
                .and()
                .csrf().disable(); //Cross domain protection
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.stereotype.Component;

/**
 * Authentication authorization Server
 */
@Component
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //Allow form submission
        security.allowFormAuthenticationForClients()
                .checkTokenAccess("permitAll()");
    }

    /**
     * appid mayikt secret= 123456
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                // appid
                .withClient("mayikt")
                // appsecret
                .secret(passwordEncoder.encode("123456"))
                // Authorization code
                .authorizedGrantTypes("authorization_code")
                // Scope
                .scopes("all")
                // id of the resource
                .resourceIds("mayikt_resource")
                // token url 
                .redirectUris("http://www.mayikt.com/callback");
    }
}

Load and run after configuration

Direct access http://localhost:8080/oauth/authorize?client_id=mayikt&response_type=code Come through OAuth

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-eRnPgBYC-1628066886995)(E:\OneDrive - xbsf.cursotamandare.g12.br \ desktop \ s.png)]

After approval, the authorization code is generated and returned to the callback address, such as www.mayikt.com com/callback? code=h7hGtB

Then get it through the authorization code tokenhttp://localhost:8080/oauth/token?code=h7hGtB&grant_type=authorization_code&redirect_uri=http://www.mayikt.com/callback&scope=all Send a post request using postman, and basic auth authorizes it

Integrate accessToken

Separate server-side projects

mayikt:
  appid: mayikt
  appsecret: 123456
server:
  port: 8081

Resource segment configuration class

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;

/**
 * Resource Server side
 */
@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Value("${mayikt.appid}")
    private String mayiktAppId;
    @Value("${mayikt.appsecret}")
    private String mayiktAppSecret;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Primary
    @Bean
    public RemoteTokenServices remoteTokenServices() {
        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        //Set authorization server check_token endpoint full address
       tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        //Set the client id and secret. Note: client_ The secret value cannot be encrypted with passwordEncoder!
        tokenServices.setClientId(mayiktAppId);
        tokenServices.setClientSecret(mayiktAppSecret);
        return tokenServices;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //Set and create session policy
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //@formatter:off
        //All requests must be authorized
        http.authorizeRequests()
                .anyRequest().authenticated();
        //@formatter:on
    }

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

Access interface

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberService {
    @GetMapping("/getMember")
    public String getMember() {
        return "Interface";
    }
}
  1. Now we are the party issuing the interface. We give our customers an appid and appsecret

  2. The customer gets the authorization code through appid, and then gets the access token through the authorization code, appid and appsecret

  3. Then the client accesses the interface and attaches an access token. The resource side will verify whether it is the client

  4. Open interface
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
    //@formatter:off
    //All requests must be authorized
    http.authorizeRequests()
    .anyRequest().authenticated();
    //@formatter:on
    }

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

Access interface

```java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberService {
    @GetMapping("/getMember")
    public String getMember() {
        return "Interface";
    }
}
  1. Now we are the party issuing the interface. We give our customers an appid and appsecret
  2. The customer gets the authorization code through appid, and then gets the access token through the authorization code, appid and appsecret
  3. Then the client accesses the interface and attaches an access token. The resource side will verify whether it is the client
  4. Open interface

Topics: Java