2014-12-16 18 views
27

Próbuję skonfigurować Spring Security za pomocą konfiguracji Java w podstawowej aplikacji internetowej, aby uwierzytelnić się w zewnętrznej usłudze internetowej za pomocą zaszyfrowanego tokena podanego w parametrze żądania adresu URL.Filtr niestandardowego uwierzytelniania Spring Security przy użyciu Java Config

Chciałbym (jak sądzę) mieć filtr bezpieczeństwa, który przechwytuje żądania z portalu logowania (wszystkie one przechodzą do/authenticate), filtr użyje dostawcy uwierzytelniania do przetworzenia logiki biznesowej procesu uwierzytelniania.

Portal logowania -> Przekieruj "\ authenticate" (+ Token) -> Uwierzytelnij Token z powrotem na Portal logowania (WS) -> Jeśli sukces dostanie role i ustawienia użytkownika.

Stworzyłem filtr ..

@Component 
public final class OEWebTokenFilter extends GenericFilterBean { 
    @Override 
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { 
     if (request instanceof HttpServletRequest) { 
      OEToken token = extractToken(request); 
      // dump token into security context (for authentication-provider to pick up) 
      SecurityContextHolder.getContext().setAuthentication(token); 
     } 
    } 
    chain.doFilter(request, response); 
} 

AuthenticationProvider ...

@Component 
public final class OEWebTokenAuthenticationProvider implements AuthenticationProvider { 
    @Autowired 
    private WebTokenService webTokenService; 

    @Override 
    public boolean supports(final Class<?> authentication) { 
     return OEWebToken.class.isAssignableFrom(authentication); 
    } 

    @Override 
    public Authentication authenticate(final Authentication authentication) { 
     if (!(authentication instanceof OEWebToken)) { 
      throw new AuthenticationServiceException("expecting a OEWebToken, got " + authentication); 
     } 

     try { 
      // validate token locally 
      OEWebToken token = (OEWebToken) authentication; 
      checkAccessToken(token); 

      // validate token remotely 
      webTokenService.validateToken(token); 

      // obtain user info from the token 
      User userFromToken = webTokenService.obtainUserInfo(token); 

      // obtain the user from the db 
      User userFromDB = userDao.findByUserName(userFromToken.getUsername()); 

      // validate the user status 
      checkUserStatus(userFromDB); 

      // update ncss db with values from OE 
      updateUserInDb(userFromToken, userFromDB); 

      // determine access rights 
      List<GrantedAuthority> roles = determineRoles(userFromDB); 

      // put account into security context (for controllers to use) 
      return new AuthenticatedAccount(userFromDB, roles); 
     } catch (AuthenticationException e) { 
      throw e; 
     } catch (Exception e) { 
      // stop non-AuthenticationExceptions. otherwise full stacktraces returned to the requester 
      throw new AuthenticationServiceException("Internal error occurred"); 
     } 
    } 

A moja Wiosna Bezpieczeństwo Config

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

    @Autowired 
    OESettings oeSettings; 

    @Bean(name="oeAuthenticationService") 
    public AuthenticationService oeAuthenticationService() throws AuthenticationServiceException { 
     return new AuthenticationServiceImpl(new OEAuthenticationServiceImpl(), oeSettings.getAuthenticateUrl(), oeSettings.getApplicationKey()); 
    } 

    @Autowired 
    private OEWebTokenFilter tokenFilter; 

    @Autowired 
    private OEWebTokenAuthenticationProvider tokenAuthenticationProvider; 

    @Autowired 
    private OEWebTokenEntryPoint tokenEntryPoint; 

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

    @Override 
    public void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(tokenAuthenticationProvider); 
    } 

    @Bean 
    public FilterRegistrationBean filterRegistrationBean() { 
     FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
     registrationBean.setFilter(tokenFilter);  
     registrationBean.setEnabled(false); 
     return registrationBean; 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable() 
      .authorizeRequests() 
      .antMatchers("/authenticate**").permitAll() 
      .antMatchers("/resources/**").hasAuthority("ROLE_USER") 
      .antMatchers("/home**").hasAuthority("ROLE_USER") 
      .antMatchers("/personSearch**").hasAuthority("ROLE_ADMIN") 
      // Spring Boot actuator endpoints 
      .antMatchers("/autoconfig**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/beans**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/configprops**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/dump**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/env**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/health**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/info**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/mappings**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/metrics**").hasAuthority("ROLE_ADMIN") 
      .antMatchers("/trace**").hasAuthority("ROLE_ADMIN") 
      .and() 
       .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class) 
       .authenticationProvider(tokenAuthenticationProvider) 
       .antMatcher("/authenticate/**") 
       .exceptionHandling().authenticationEntryPoint(tokenEntryPoint) 
      .and() 
       .logout().logoutSuccessUrl(oeSettings.getUrl()); 
    } 
} 

Mój problem jest konfiguracja filtra w mojej klasie SpringConfig. Chcę, aby filtr działał tylko wtedy, gdy żądanie dotyczy/authenticate URL, dodałem .antMatcher ("/ authenticate/**") do konfiguracji filtru.

.and() 
       .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class) 
       .authenticationProvider(tokenAuthenticationProvider) 
       .antMatcher("/authenticate/**") 
       .exceptionHandling().authenticationEntryPoint(tokenEntryPoint) 

Kiedy mam tej linii we wszystkich innych adresów URL nie są zabezpieczone, mogę ręcznie przejść do katalogu/home bez uwierzytelniania, usunąć linię i/home jest uwierzytelniona.

Czy powinienem zadeklarować filtr, który ma zastosowanie tylko do określonego adresu URL?

Jak mogę to wdrożyć, zachowując jednocześnie bezpieczeństwo innych adresów URL?

+0

Dzięki dla quetsion. :) Pomaga! – raj

Odpowiedz

12

mam rozwiązany mój problem wykonując sprawdzić stan uwierzytelniania w filtrze przed involking dostawcy uwierzytelniania ....

Config

.and() 
    .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class) 
    .authenticationProvider(tokenAuthenticationProvider) 
    .exceptionHandling().authenticationEntryPoint(tokenEntryPoint) 

Filtr

@Override 
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) 
     throws IOException, ServletException { 

    logger.debug(this + "received authentication request from " + request.getRemoteHost() + " to " + request.getLocalName()); 

    if (request instanceof HttpServletRequest) { 
     if (isAuthenticationRequired()) { 
      // extract token from header 
      OEWebToken token = extractToken(request); 

      // dump token into security context (for authentication-provider to pick up) 
      SecurityContextHolder.getContext().setAuthentication(token); 
     } else { 
      logger.debug("session already contained valid Authentication - not checking again"); 
     } 
    } 

    chain.doFilter(request, response); 
} 

    private boolean isAuthenticationRequired() { 
    // apparently filters have to check this themselves. So make sure they have a proper AuthenticatedAccount in their session. 
    Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); 
    if ((existingAuth == null) || !existingAuth.isAuthenticated()) { 
     return true; 
    } 

    if (!(existingAuth instanceof AuthenticatedAccount)) { 
     return true; 
    } 

    // current session already authenticated 
    return false; 
} 
+4

Czy możesz opublikować kod tych klas: implementacja metody "OEWebToken", "AuthenticatedAccount" i "extractToken (request)'? Bardzo bym mi pomógł z moją usługą odpoczynku. Z góry dziękuję. – masterdany88

Powiązane problemy