A Spring Security component that recently implemented multi-login is very silky, out-of-the-box, pluggable, and flexible. I think I can do most of the scenes. At present, we have completed two kinds of custom login, namely mobile phone number verification code and wechat mini program, plus the default Form login, there are three kinds in total, now open source to share with you. Next, we will briefly introduce this plug-in package.

DSL configuration Style

To cut to the chase, let’s start with configuration:

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .mvcMatchers("/foo/**")
                .access("hasAuthority('ROLE_USER')").anyRequest().authenticated()
                .and()
                // The default form login
                .formLogin()
                .and()
                .apply(new LoginFilterSecurityConfigurer<>())
                // Verification code login
                .captchaLogin(captchaLoginConfigurer ->
                                // Verification code 1 Configure the highest priority 2. Register as a Spring Bean without configuration
                                captchaLoginConfigurer.captchaService(this::verifyCaptchaMock)
                                        // Query the user by mobile phone UserDetials 1 Set the highest priority 2 here. Registering as a Spring Bean does not require configuration
                                        .captchaUserDetailsService(this::loadUserByPhoneMock)
                                        // Generate JWT returns 1. Configure the highest priority 2 here. Register as a Spring Bean without configuration
                                        .jwtTokenGenerator(this::tokenResponseMock)
                        // Todo other configuration omitted......
                )
                // Applet login supports multiple applets at the same time
                .miniAppLogin(miniAppLoginConfigurer -> miniAppLoginConfigurer
                                // Implement applet multi-tenant
                                // Query the appID and secret of the clientid applets according to the request
                                .miniAppClientService(this::miniAppClientMock)
                                // Applet user automatic registration and retrieval 1 Configure the highest priority here. 2 Register as a Spring Bean without configuration
                                .miniAppUserDetailsService(new MiniAppUserDetailsServiceMock())
                                // The expiration time of the sessionKey cache should be less than that stated in the official document of wechat
                                .miniAppSessionKeyCache(new MiniAppSessionKeyCacheMock())
                                // Generate JWT returns 1. Configure the highest priority 2 here. Register as a Spring Bean without configuration
                                .jwtTokenGenerator(this::tokenResponseMock)
                        // Todo other configuration omitted......
                );

        return http.build();
    }
Copy the code

This style perfectly aligns with Spring Security’s DSL configuration style, which is not only elegant, but also configurable on demand. Delete the captchaLogin method if you don’t have a verification code; Delete the miniAppLogin method if you don’t have a wechat applet login. There is even fine-grained customization for single logins. FormLogin has both basic verification code login and wechat mini program login.

Why so flexible?

Here we abstract a login configuration class:

 public abstract class AbstractLoginFilterConfigurer<H extends HttpSecurityBuilder<H>, 
         C extends AbstractLoginFilterConfigurer<H.C.F>, 
         F extends AbstractAuthenticationProcessingFilter>
         extends AbstractHttpConfigurer<AbstractLoginFilterConfigurer<H.C.F>, H> {
             / / omit...
         }
Copy the code

All additional login channel can be extended through this class, be responsible for the verification code login CaptchaLoginFilterConfigurer and WeChat applet login MiniAppLoginFilterConfigurer are the class, Basically you read the source code can also copy a copy.

In addition, these configuration items can be placed in the Spring IoC, the configuration class can automatically obtain, but the highest priority is the implementation of the configuration in the above code, the principle of the following example:

  @Override
     protected AuthenticationSuccessHandler defaultSuccessHandler(H http) {
         // If the configuration class is not configured, try to find it in Spring IoC
         if (this.jwtTokenGenerator == null) {
             ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
             jwtTokenGenerator = getBeanOrNull(applicationContext, JwtTokenGenerator.class);
         }
         Assert.notNull(jwtTokenGenerator, "jwtTokenGenerator is required");
         return new LoginAuthenticationSuccessHandler(jwtTokenGenerator);
     }
 ​
 ​
     public final <T> T getBeanOrNull(ApplicationContext applicationContext, Class<T> beanType) {
         String[] beanNames = applicationContext.getBeanNamesForType(beanType);
         if (beanNames.length == 1) {
             return applicationContext.getBean(beanNames[0], beanType);
         }
         return null;
     }
Copy the code

Method of use

Install to your local repository using the Maven command MVN.

        <dependency>
            <groupId>cn.felord</groupId>
            <artifactId>spring-security-extension</artifactId>
            <version>1.0.0</version>
        </dependency>
Copy the code

Then refer to the sample project for development. There are three login methods.

Normal login

Native Spring Security interface

POST /login? username=user&password=12345 HTTP / 1.1
Host: localhost:8080
Copy the code

Verification code login

The necessary configuration interfaces need to be implemented first

Call verification code login interface after sending verification code:

POST /login/captcha? phone=11111111111&captcha=123123 HTTP / 1.1
Host: localhost:8080
Copy the code

Applets login

The necessary configuration interfaces need to be implemented first

The front end first invokes wechat authorized login interface to obtain openID:

POST /miniapp/preauth? clientId=wxxda23234&jsCode=051A23234ZHa1tZ5yj3AOlFr HTTP / 1.1
Host: localhost:8080
Copy the code

Response:

{
    "code": 200."data": {
        "errcode": null."errmsg": null."sessionKey": null."openid": "oWmZj5QBrZxxxxx8OUxRrZJi4"."unionid": "oS-dxxxxxx4w_x7dA-h9MIuA"
    },
    "msg": ""."identifier": true
}
Copy the code

Then invoke the applet login interface:

POST /login/miniapp HTTP / 1.1
Host: localhost:8080
Content-Type: application/json

{
    "clientId": "wxd14qr6"."openId": "oWmZj5QBrZIBks0xx8OUxRrZJi4"."unionId": "oS-dK520tgW8xxxx7dA-h9MIuA"."iv":"LQUOt8BSTa7xxxpe1Q=="."encryptedData": "10hn3o4xxxxxrO/Ag5nRD3QkLSzduKnWuzN9B/H4Y0G5mDPR8siA7T8yaaqZsrMycLAoe2qrd1J75yYetYuWifiq3jUrcceRZHVxxl9LnQdW8f5+pMTnQtC YiMJ7Jm9paCw2Bh+5Lowkyqkx1q0fALvCQ9LXPPLAbLOB9CavRfKoenAmyyHQjZ/6lz0njzA=="
}
Copy the code

access