1. Introduction

Welcome to Spring Security’s hands-on dry goods series. A developer recently asked an interesting question. He is working on a project involving two styles, one is to interface small programs and use stateless JWT tokens for security; The other is to manage the backend using a Freemarker, a Session mechanism that does not separate the front and back ends. What do I do with Spring Security?

2. Solutions

We can use multiple inheritance WebSecurityConfigurerAdapter build multiple HttpSecurity. The HttpSecurity object tells us how to authenticate the user, how to do access control, what policies to use, and so on.

If you’ve seen the previous tutorial, here’s how we configured it:

/** * Single policy configuration **@author felord.cn
 * @see org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
 * @since 14 :58 2019/10/15
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
@EnableWebSecurity
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class CustomSpringBootWebSecurityConfiguration {
    
    /** * The type Default configurer adapter. */
    @Configuration
    @Order(SecurityProperties.BASIC_AUTH_ORDER)
    static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            super.configure(auth);
        }

        @Override
        public void configure(WebSecurity web) {
            super.configure(web);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            / / configuration httpSecurity}}}Copy the code

The configuration above a HttpSecurity, we did add a WebSecurityConfigurerAdapter subclass to configure another HttpSecurity. There are still many problems to be solved.

2.1 How to Route Different Security Configurations

After configuring two HttpSecurity interfaces, how does the applet interface and background interface go through the corresponding HttpSecurity?

Httpsecurity.antmatcher (String antPattern) provides a filtering mechanism. For example, we configure:

     @Override
        protected void configure(HttpSecurity http) throws Exception {
            / / configuration httpSecurity
            http.antMatcher("/admin/v1");

        }
Copy the code

Then this HttpSecurity will only be available for all urls starting with /admin/v1. This requires us to specify uniform URL prefixes for different clients.

Any functionality provided by HttpSecurity can be customized. Such as login method, role system and so on.

2.2 How do I specify the default HttpSecurity

We can use @ Order on WebSecurityConfigurerAdapter realize annotations to specify the priority, the lower the value, the greater the priority, no @ Order comments will be the lowest priority.

2.3 How Do I Configure Different UserDetailsServices

In many cases we hope completely isolated ordinary users and management, we need more UserDetailsService, you can in the following method to specific Settings to configure AuthenticationManagerBuilder UserDetailsService, You can also configure different password policies.

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    daoAuthenticationProvider.setUserDetailsService(new UserDetailsService() {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // self-implement
            return  null; }});// You can also design specific password policies
    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
    auth.authenticationProvider(daoAuthenticationProvider);
}
Copy the code

2.4 Final Configuration Template

With the above problems solved, we have basically mastered the implementation of multiple security policies in an application. The configuration template is as follows:

/** * Multiple policy configurations **@author felord.cn
 * @see org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
 * @since 14 :58 2019/10/15
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
@EnableWebSecurity
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class CustomSpringBootWebSecurityConfiguration {

    /** * Background interface security policy. The default configuration is */
    @Configuration
    @Order(1)
    static class AdminConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
            // User details are personalized
            daoAuthenticationProvider.setUserDetailsService(new UserDetailsService() {
                @Override
                public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                    // self-implement
                    return null; }});// You can also design specific password policies
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
            auth.authenticationProvider(daoAuthenticationProvider);
        }

        @Override
        public void configure(WebSecurity web) {
            super.configure(web);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // Customize as required
            http.antMatcher("/admin/v1") .sessionManagement(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()); }}/** * App interface security policy. There is no {@linkOrder} annotation priority is lower than above */
    @Configuration
    static class AppConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
            // User details are personalized
            daoAuthenticationProvider.setUserDetailsService(new UserDetailsService() {
                @Override
                public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                    // self-implement
                    return null; }});// You can also design specific password policies
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
            auth.authenticationProvider(daoAuthenticationProvider);
        }

        @Override
        public void configure(WebSecurity web) {
            super.configure(web);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // Customize as required
            http.antMatcher("/app/v1") .sessionManagement(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()); }}}Copy the code

3. Summary

Today we worked out how to adopt different security policies for different types of interfaces. Hope you find it useful and leave a message if you have any questions. A lot of attention: code farmers small fat brother, more dry goods to serve.

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn