2015-09-24 6 views
0

Мы настраиваем Spring Security в приложении 1.3 Spring Boot. Мы создали класс для настройки всего с конфигурацией Java, но по какой-то причине каждый раз, когда я пытаюсь получить доступ к любому URL-адресу, настроенному на «allowAll()», я получаю ответ на сообщение, подобный этому:Конфигурация системы безопасности Spring с доступом блокировки JWT/antMatchers

{ 
    "timestamp": 1443099232454, 
    "status": 403, 
    "error": "Forbidden", 
    "message": "Access Denied", 
    "path": "/api/register" 
} 

Я не совсем уверен, почему я получаю это, если я настраиваю antMatchers, чтобы разрешить доступ к URL-адресам регистрации, аутентификации и активации. Если я отключу эти три строки, я смогу получить доступ к этим трем конечным точкам.

Это моя текущая конфигурация:

SecurityConfig.java

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) 
@Order(1) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Inject 
    private Http401UnauthorizedEntryPoint authenticationEntryPoint; 

    @Inject 
    private UserDetailsService userDetailsService; 

    @Inject 
    private TokenProvider tokenProvider; 

    public SecurityConfig() { 
     super(true); 
    } 

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

    @Inject 
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     // @formatter:off 
     http 
      .exceptionHandling() 
      .authenticationEntryPoint(authenticationEntryPoint) 
     .and() 
      .csrf() 
      .disable() 
      .headers() 
      .frameOptions() 
      .disable() 
     .and() 
      .sessionManagement() 
      .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
     .and() 
      .authorizeRequests() 
      .antMatchers("/api/register").permitAll() 
      .antMatchers("/api/activate").permitAll() 
      .antMatchers("/api/authenticate").permitAll() 
     .and() 
      .authorizeRequests() 
      .anyRequest() 
      .authenticated() 
     .and() 
      .apply(securityConfigurerAdapter()); 
     // @formatter:on 
    } 

    private JwtTokenConfigurer securityConfigurerAdapter() { 
     return new JwtTokenConfigurer(tokenProvider); 
    } 
} 

UserDetailsService.java

@Service("userDetailsService") 
@Log4j2 
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService { 

    @Inject 
    private UserRepository userRepository; 

    @Override 
    public UserDetails loadUserByUsername(final String email) { 
     log.debug("Authenticating {}", email); 
     String lowercaseEmail = email.toLowerCase(); 
     Optional<User> userFromDatabase = userRepository.findOneByEmail(lowercaseEmail); 
     return userFromDatabase.map(
       user -> { 
        if (!user.isEnabled()) { 
         throw new DisabledException("User " + lowercaseEmail + " is disabled"); 
        } 

        List<GrantedAuthority> grantedAuthorities = user.getRoles().stream() 
          .map(role -> role.getGrantedAuthority()).collect(Collectors.toList()); 

        return new org.springframework.security.core.userdetails.User(lowercaseEmail, user.getPassword(), 
         grantedAuthorities); 
       }).orElseThrow(
       () -> new UsernameNotFoundException("User " + lowercaseEmail + " was not found in the database")); 
    } 
} 

JwtTokenConfigurer.java

public class JwtTokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { 

    private TokenProvider tokenProvider; 

    public JwtTokenConfigurer(TokenProvider tokenProvider) { 
     this.tokenProvider = tokenProvider; 
    } 

    @Override 
    public void configure(HttpSecurity http) throws Exception { 
     JwtTokenFilter customFilter = new JwtTokenFilter(tokenProvider); 
     http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); 
    } 
} 

JwtTokenFilter.java

public class JwtTokenFilter extends GenericFilterBean { 
    private final static String JWT_TOKEN_HEADER_NAME = "Authorization"; 
    private TokenProvider tokenProvider; 

    public JwtTokenFilter(TokenProvider tokenProvider) { 
     this.tokenProvider = tokenProvider; 
    } 

    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
     throws IOException, ServletException { 
     try { 
      HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 
      String jwtToken = httpServletRequest.getHeader(JWT_TOKEN_HEADER_NAME); 

      if (StringUtils.hasText(jwtToken)) { 
       String authorizationSchema = "Bearer"; 
       if (jwtToken.indexOf(authorizationSchema) == -1) { 
        throw new InsufficientAuthenticationException("Authorization schema not found"); 
       } 
       jwtToken = jwtToken.substring(authorizationSchema.length()).trim(); 

       JwtClaims claims = tokenProvider.parseToken(jwtToken); 
       String email = (String) claims.getClaimValue(TokenConstants.EMAIL.name()); 
       List<GrantedAuthority> grantedAuthorities = claims.getStringListClaimValue(TokenConstants.ROLES.name()) 
        .stream().map(role -> new SimpleGrantedAuthority(role)).collect(Collectors.toList()); 

       UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
        email, null, grantedAuthorities); 
       SecurityContextHolder.getContext().setAuthentication(authenticationToken); 
      } 
      filterChain.doFilter(servletRequest, servletResponse); 
     } catch (Exception ex) { 
      throw new RuntimeException(ex); 
     } 
    } 
} 

Http401UnauthorizedEntryPoint.java

@Component 
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint { 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) 
     throws IOException, ServletException { 
     log.debug("Pre-authenticated entry point called. Rejecting access"); 
     response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied"); 
    } 
} 

Как я уже говорил раньше, каждый раз, когда я пытаюсь получить доступ к любому из этих трех конечных точек:

.antMatchers("/api/register").permitAll() 
.antMatchers("/api/activate").permitAll() 
.antMatchers("/api/authenticate").permitAll() 

Я получаю доступ отрицательным ... Любые идеи?

+0

Вы можете оставить/API/регистрация контроллер? Проверьте, что происходит в FilterSecurityInterceptor. Похоже, вы запрашиваете какое-то разрешение в/api/register. Возможно, с аннотациями PreAuthorize или Secured в классе Controller, которые действительны для всех методов. – gabrielgiussi

ответ

1

Необходимо разрешить анонимные пользователи.

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    // @formatter:off 
    http 
     .exceptionHandling() 
     .authenticationEntryPoint(authenticationEntryPoint) 
    .and() 
     .csrf() 
     .disable() 
     .headers() 
     .frameOptions() 
     .disable() 
    .and() 
     .sessionManagement() 
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
    .and() 
     .authorizeRequests() 
     .antMatchers("/api/register").permitAll() 
     .antMatchers("/api/activate").permitAll() 
     .antMatchers("/api/authenticate").permitAll() 
    .and() 
     .anonymous() 
     .authorizeRequests() 
     .anyRequest() 
     .authenticated() 
    .and() 
     .apply(securityConfigurerAdapter()); 
    // @formatter:on 
} 

Потому что AbstractSecurityInterceptor всегда спрашивает, есть ли что-то в SecurityContextHolder. AbstractSecurityInterceptor#beforeInvocation линия 221

if (SecurityContextHolder.getContext().getAuthentication() == null) { 
credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound","An Authentication object was not found in the SecurityContext"),object, attributes); 

} 
Смежные вопросы