InitBinder将验证器绑定到某些参数

时间:2018-10-27 19:10:00

标签: java spring

我在控制器中使用@InitBinder

@InitBinder
public void binder(WebDataBinder binder) {
    binder.addValidators(new CompoundValidator(new Validator[] {
            new UserAccountValidator()}));
}

@Override
public UserAccountEntity login(@RequestBody UserAccountEntity userAccount,
        HttpServletResponse response) throws InvalidCredentialsException, InactiveAccountException {
    return userAccountService.authenticateUserAndSetResponsenHeader(
            account.getUsername(), account.getPassword(), response);
}

@Override
public UserAccountEntity create(@Valid @RequestBody UserAccountEntity userAccount,
        HttpServletResponse response) throws EntityExistsException, InvalidCredentialsException, InactiveAccountException {
    String username = userAccount.getUsername();
    String password = userAccount.getPassword();
    userAccountService.saveIfNotExistsOrExpired(username, password);
    return userAccountService.authenticateUserAndSetResponsenHeader(
            username, password, response);
}

我希望验证器仅验证登录端点的传入userAccount,而不验证create方法。现在,它在两种方法上都可以验证。

更新1

CompoundValidator的代码:

public final class CompoundValidator implements Validator {

    private final Validator[] validators;

    public CompoundValidator(final Validator[] validators) {
        super();
        this.validators=validators;
    }

    @Override
    public boolean supports(final Class<?> clazz) {
        for (Validator v : validators) {
            if (v.supports(clazz)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void validate(Object target, Errors errors) {
        for (Validator v : validators) {
            if (v.supports(target.getClass())) {
                v.validate(target, errors);
            }
        }
    }
}

更新2

一些配置文件:

@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserAccountService userAccountService;

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

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        // TODO re-enable csrf after dev is done
        .csrf()
                .disable()
                // we must specify ordering for our custom filter, otherwise it
                // doesn't work
                .addFilterAfter(jwtAuthenticationFilter(),
                        UsernamePasswordAuthenticationFilter.class)
                // we don't need Session, as we are using jwt instead. Sessions
                // are harder to scale and manage
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    /*
     * Ignores the authentication endpoints (signup and login)
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/api/authentication/**").and().ignoring()
                .antMatchers(HttpMethod.OPTIONS, "/**");
    }

    /*
     * Set user details services and password encoder
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.userDetailsService(userAccountService).passwordEncoder(
                passwordEncoder());
    }

    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }

    /*
     * By default, spring boot adds custom filters to the filter chain which
     * affects all requests this should be disabled.
     */
    @Bean
    public FilterRegistrationBean<JwtAuthenticationFilter> rolesAuthenticationFilterRegistrationDisable(
            JwtAuthenticationFilter filter) {
        FilterRegistrationBean<JwtAuthenticationFilter> registration = new FilterRegistrationBean<JwtAuthenticationFilter>(
                filter);
        registration.setEnabled(false);
        return registration;
    }
}

-

@Configuration
public class AppConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
            .addResourceLocations("classpath:/public/")
            .resourceChain(false).addResolver(new CustomResourceResolver());
}

private class CustomResourceResolver implements ResourceResolver {
    private Resource index = new ClassPathResource("/public/index.html");
    private List<String> handledExtensions = Arrays.asList("css", "png",
            "svg", "jpg", "jpeg", "gif", "ico", "js");

    private List<String> ignoredPaths = Arrays.asList("^api\\/.*$");

    @Override
    public Resource resolveResource(HttpServletRequest request,
            String requestPath, List<? extends Resource> locations,
            ResourceResolverChain chain) {
        return resolve(requestPath, locations);
    }

    @Override
    public String resolveUrlPath(String resourcePath,
            List<? extends Resource> locations, ResourceResolverChain chain) {
        Resource resolvedResource = resolve(resourcePath, locations);
        if (resolvedResource == null) {
            return null;
        }
        try {
            return resolvedResource.getURL().toString();
        } catch (IOException e) {
            return resolvedResource.getFilename();
        }
    }

    private Resource resolve(String requestPath,
            List<? extends Resource> locations) {
        if (isIgnored(requestPath)) {
            return null;
        }
        if (isHandled(requestPath)) {
            return locations
                    .stream()
                    .map(loc -> createRelative(loc, requestPath))
                    .filter(resource -> resource != null
                            && resource.exists()).findFirst()
                    .orElseGet(null);
        }
        return index;
    }

    private Resource createRelative(Resource resource, String relativePath) {
        try {
            return resource.createRelative(relativePath);
        } catch (IOException e) {
            return null;
        }
    }

    private boolean isIgnored(String path) {
        return !ignoredPaths.stream().noneMatch(
                rgx -> Pattern.matches(rgx, path));
    }

    private boolean isHandled(String path) {
        String extension = StringUtils.getFilenameExtension(path);
        return handledExtensions.stream().anyMatch(
                ext -> ext.equals(extension));
    }
}

// TODO remove this after active development of the front-end
@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .exposedHeaders("Authorization", "Content-Type")
            .allowedMethods("*");
}

}

0 个答案:

没有答案