liangcmwn / docs

mydocs on git
0 stars 0 forks source link

Spring Webflux + Spring Security #15

Open liangcmwn opened 5 years ago

liangcmwn commented 5 years ago

maven引入: webflux

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

spring security

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
liangcmwn commented 5 years ago

添加注解 @EnableWebFluxSecurity

public class AuthSecurityConfiguration {

    @Autowired
    private ApplicationContext applicationContext;

    //认证异常返回消息
    @Bean
    public RestServerAuthenticationEntryPoint serverAuthenticationEntryPoint(ObjectMapper objectMapper) {
        return new RestServerAuthenticationEntryPoint(objectMapper);
    }
    //认证成功返回消息
    @Bean
    public RestAuthenticationSuccessHandler serverAuthenticationSuccessHandler(ObjectMapper objectMapper) {
        return new RestAuthenticationSuccessHandler(objectMapper);
    }
    //认证失败返回消息
    @Bean
    public RestServerAuthenticationFailureHandler serverAuthenticationFailureHandler(RestServerAuthenticationEntryPoint serverAuthenticationEntryPoint) {
        return new RestServerAuthenticationFailureHandler(serverAuthenticationEntryPoint);
    }
    //详细配置
    @Bean
    SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
        ServerAuthenticationEntryPoint serverAuthenticationEntryPoint = lookup(RestServerAuthenticationEntryPoint.class);
        //session存储
        ServerSecurityContextRepository securityContextRepository = new WebSessionServerSecurityContextRepository();
        http.csrf().disable()
                .securityContextRepository(securityContextRepository)
                .exceptionHandling().authenticationEntryPoint(serverAuthenticationEntryPoint)
                .and()
                //.httpBasic().disable()
                //.formLogin().disable()
                .authorizeExchange()
                .pathMatchers("/api/auth/**", "/api/di/v1/**").permitAll()
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                .anyExchange().authenticated();
        //自定义认证(jwt...)
        LoginFilter loginFilter = lookup(LoginFilter.class);
        loginFilter.setSecurityContextRepository(securityContextRepository);
        http.addFilterAt(loginFilter, SecurityWebFiltersOrder.FORM_LOGIN);
        return http.build();
    }
    //自定义authenticationManager
    @Bean
    AvatarReactiveAuthenticationManager authenticationManager(@Lazy AccountApiClient apiClient) {
        return new AvatarReactiveAuthenticationManager(apiClient);
    }

    @Bean
    LoginFilter loginFilter(ReactiveAuthenticationManager authenticationManager, ObjectMapper objectMapper,
                            PatchcaHelper helper, RestAuthenticationSuccessHandler serverAuthenticationSuccessHandler,
                            RestServerAuthenticationFailureHandler serverAuthenticationFailureHandler) {
        LoginFilter loginFilter = new LoginFilter(authenticationManager, "/api/auth/jwt", objectMapper, helper);
        loginFilter.setAuthenticationFailureHandler(serverAuthenticationFailureHandler);
        loginFilter.setAuthenticationSuccessHandler(serverAuthenticationSuccessHandler);
        return loginFilter;
    }

    protected <T> T lookup(Class clazz) {
        return (T) applicationContext.getBean(clazz);
    }
}
liangcmwn commented 5 years ago

认证拦截器

public class LoginFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain)
            throws AuthenticationException {
        return matches(exchange)
                .filter(result -> result)
                .flatMap(result -> convert(exchange))
                .switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
                .flatMap(request -> authenticate(exchange, chain, request))
                ;
    }
}
liangcmwn commented 5 years ago

ServerHttpSecurity 的详细构造过程参照build()方法