Фильтры Spring Boot и Spring Security не фильтруют правильный запрос - PullRequest
0 голосов
/ 08 июля 2019

У меня есть пружинный ботинок и служба безопасности весны.Я расширил класс WebSecurityConfigurerAdapter и переопределил метод настройки.Но почему-то он не фильтрует правильный запрос.

Мой URL-адрес похож на

localhost:8080/album/private/v1/getAlbumsByVendorId?vendorId=1
 localhost:8080/vendor/private/v1/getVendor?vendorId=1

, а также у меня есть URL-адрес, который я не хочу аутентифицировать. Например, ниже URL-адреса.

localhost:8080/category/v1/getCategory

Требуется только аутентификация, если URL-адрес содержит частный.Но похоже, что мой фильтр вызывается для всех запросов.что-то не так в .antMatchers("/**/private/**")

Примечание. У меня нет никакого контекстного пути на данный момент.Добавлены занятия.Контроллер - просто фиктивный тестовый контроллер.

@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private UserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // configure AuthenticationManager so that it knows from where to load
        // user for matching credentials
        // Use BCryptPasswordEncoder
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

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

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

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
        .csrf().disable()
        .cors().disable()
        .authorizeRequests()
        .antMatchers("/authenticate").permitAll()
        .antMatchers("/**/private/**").authenticated()
        .anyRequest().authenticated()
        .and()
        .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
    }
}


    @Component
    public class JWTAuthenticationFilter extends OncePerRequestFilter {

        @Autowired
        private JwtUserDetailsService jwtUserDetailsService;

        @Autowired
        private JwtTokenUtil jwtTokenUtil;

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
                throws ServletException, IOException {

            final String requestTokenHeader = request.getHeader("Authorization");

            String username = null;
            String jwtToken = null;
            // JWT Token is in the form "Bearer token". Remove Bearer word and get only the Token
            if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
                jwtToken = requestTokenHeader.substring(7);
                try {
                    username = jwtTokenUtil.getUsernameFromToken(jwtToken);
                } catch (IllegalArgumentException e) {
                    System.out.println("Unable to get JWT Token");
                } catch (ExpiredJwtException e) {
                    System.out.println("JWT Token has expired");
                }
            } else {
                logger.warn("JWT Token does not begin with Bearer String");
            }

            //Once we get the token validate it.
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

                UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

                // if token is valid configure Spring Security to manually set authentication
                if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // After setting the Authentication in the context, we specify
                    // that the current user is authenticated. So it passes the Spring Security Configurations successfully.
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }
            }
            chain.doFilter(request, response);
        }

    }



@RestController
@CrossOrigin()
public class HelloWorldController {

    @RequestMapping({ "/hello" })
    public String hello() {
        return "Hello World";
    }

    @RequestMapping({ "/private/test" })
    public String hello2() {
        return "Hello World-test";
    }

    @RequestMapping({ "/v1/private/test" })
    public String hello3() {
        return "Hello World-test-v1";
    }

    @RequestMapping({ "/v1/public/test" })
    public String hello4() {
        return "Hello World-test-v1-public";
    }

}

1 Ответ

0 голосов
/ 08 июля 2019

По умолчанию Spring Boot защищает все конечные точки, когда Spring Security находится на пути к классам.Нам нужно явно добавить исключение для всех других конечных точек, которые будут разрешены без аутентификации.Рассмотрим изменение .anyRequest().permitAll(), что означает, что каждый запрос, отличный от /**/private/**, будет доступен каждому.Другими словами, фильтр будет применяться только к /**/private/**

Git Link

подход 1 (чистый путь)

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .cors().disable()
        .authorizeRequests()
            .antMatchers("/authenticate").permitAll()
            .antMatchers("/**/private/**").authenticated()
            .anyRequest().permitAll()
            .and()
        .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
    }

подход 2: проверять токен только в том случае, если запрос поступил от / private / (не идеальный способ)

JwtAuthenticationEntryPoint.java

@Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException {

        System.out.println("Entry Request: "+request.getRequestURI());
        System.out.println("Entry Contain: "+request.getRequestURI().contains("private"));
        if(request.getRequestURI().contains("private")==true) 
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");

    } 

JwtRequestFilter.java

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        final String requestTokenHeader = request.getHeader("Authorization");
        System.out.println("JWT Request: "+request.getRequestURI());
        System.out.println("JWT Contain: "+request.getRequestURI().contains("private"));
        String username = null;
        String jwtToken = null;
        //Remove comment for second approach
        if(request.getRequestURI().contains("private")==false)
        {
            System.out.println("Do Noting, Permit It");
            chain.doFilter(request, response);
        }
        else if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ") ) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                System.out.println("Unable to get JWT Token");
            } catch (ExpiredJwtException e) {
                System.out.println("JWT Token has expired");
            }
        } else {
            logger.warn("JWT Token does not begin with Bearer String");
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }

http://localhost:8080/v1/private/test **401**

http://localhost:8080/v1/private/test

http://localhost:8080/v1/public/test **200**

http://localhost:8080/v1/public/test

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...