Spring webflux custom authentication for API

前端 未结 4 1219
囚心锁ツ
囚心锁ツ 2020-12-07 23:07

I am creating an API for an Angular 5 application. I would like to use JWT for authentication.
I would like to use the features that are provided by spring security so I

4条回答
  •  旧时难觅i
    2020-12-08 00:03

    After a lot of searching and trying I think I have found the solution:

    You need a bean of SecurityWebFilterChain that contains all configuration.
    This is mine:

    @Configuration
    public class SecurityConfiguration {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private SecurityContextRepository securityContextRepository;
    
        @Bean
        public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
            // Disable default security.
            http.httpBasic().disable();
            http.formLogin().disable();
            http.csrf().disable();
            http.logout().disable();
    
            // Add custom security.
            http.authenticationManager(this.authenticationManager);
            http.securityContextRepository(this.securityContextRepository);
    
            // Disable authentication for `/auth/**` routes.
            http.authorizeExchange().pathMatchers("/auth/**").permitAll();
            http.authorizeExchange().anyExchange().authenticated();
    
            return http.build();
        }
    }
    

    I've disabled httpBasic, formLogin, csrf and logout so I could make my custom authentication.

    By setting the AuthenticationManager and SecurityContextRepository I overridden the default spring security configuration for checking if a user is authenticated/authorized for a request.

    The authentication manager:

    @Component
    public class AuthenticationManager implements ReactiveAuthenticationManager {
    
        @Override
        public Mono authenticate(Authentication authentication) {
            // JwtAuthenticationToken is my custom token.
            if (authentication instanceof JwtAuthenticationToken) {
                authentication.setAuthenticated(true);
            }
            return Mono.just(authentication);
        }
    }
    

    I am not fully sure where the authentication manager is for, but I think for doing the final authentication, so setting authentication.setAuthenticated(true); when everything is right.

    SecurityContextRepository:

    @Component
    public class SecurityContextRepository implements ServerSecurityContextRepository {
    
        @Override
        public Mono save(ServerWebExchange serverWebExchange, SecurityContext securityContext) {
            // Don't know yet where this is for.
            return null;
        }
    
        @Override
        public Mono load(ServerWebExchange serverWebExchange) {
            // JwtAuthenticationToken and GuestAuthenticationToken are custom Authentication tokens.
            Authentication authentication = (/* check if authenticated based on headers in serverWebExchange */) ? 
                new JwtAuthenticationToken(...) :
                new GuestAuthenticationToken();
            return new SecurityContextImpl(authentication);
        }
    }
    

    In the load I will check based on the headers in the serverWebExchange if the user is authenticated. I use https://github.com/jwtk/jjwt. I return a different kind of authentication token if the user is authenticated or not.

提交回复
热议问题