Próbuję zaimplementować niestandardową logikę uwierzytelniania z najnowszą wersją Spring Boot, Web i Security, ale mam problemy z niektórymi problemami. Próbowałem wielu rozwiązań w podobnych pytaniach/tutorialach bez powodzenia lub zrozumienia, co faktycznie się dzieje.Wiosenny niestandardowy filtr uwierzytelniania i dostawca nie wywołujący metody sterownika
Tworzę aplikację REST z uwierzytelnieniem bezstanowym, tzn. Istnieje punkt końcowy REST (/ web/auth/login), który oczekuje nazwy użytkownika i hasła i zwraca token ciąg znaków, który jest następnie używany we wszystkich innych punktach końcowych REST (/ api/**) w celu identyfikacji użytkownika. Muszę zaimplementować niestandardowe rozwiązanie, ponieważ uwierzytelnianie stanie się bardziej złożone w przyszłości i chciałbym zrozumieć podstawy Spring Security.
Aby osiągnąć uwierzytelnianie tokena, tworzę niestandardowy filtr i dostawcy:
Filtr:
public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public TokenAuthenticationFilter() {
super(new AntPathRequestMatcher("/api/**", "GET"));
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String token = request.getParameter("token");
if (token == null || token.length() == 0) {
throw new BadCredentialsException("Missing token");
}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(token, null);
return getAuthenticationManager().authenticate(authenticationToken);
}
}
Dostawca:
@Component
public class TokenAuthenticationProvider implements AuthenticationProvider {
@Autowired
private AuthenticationTokenManager tokenManager;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String token = (String)authentication.getPrincipal();
return tokenManager.getAuthenticationByToken(token);
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
}
config:
@EnableWebSecurity
@Order(1)
public class TokenAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private TokenAuthenticationProvider authProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**")
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(authenticationFilter(), BasicAuthenticationFilter.class);
}
@Bean
public TokenAuthenticationFilter authenticationFilter() throws Exception {
TokenAuthenticationFilter tokenProcessingFilter = new TokenAuthenticationFilter();
tokenProcessingFilter.setAuthenticationManager(authenticationManager());
return tokenProcessingFilter;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
}
AuthenticationTokenManager stosowany w operatora (a także w procesie logowania):
@Component
public class AuthenticationTokenManager {
private Map<String, AuthenticationToken> tokens;
public AuthenticationTokenManager() {
tokens = new HashMap<>();
}
private String generateToken(AuthenticationToken authentication) {
return UUID.randomUUID().toString();
}
public String addAuthentication(AuthenticationToken authentication) {
String token = generateToken(authentication);
tokens.put(token, authentication);
return token;
}
public AuthenticationToken getAuthenticationByToken(String token) {
return tokens.get(token);
}
}
Co się dzieje: Jestem dołączając poprawny wyraz w żądaniu „/ api/bla "(który jest kontrolerem REST zwracającym część Json). Filtr i dostawca zostają wywołane. Problem jest następujący:, przeglądarka jest przekierowywana do "/" zamiast wywoływania żądanej metody kontrolera REST. Wydaje się, że dzieje się to w narzędziu SavedRequestAwareAuthenticationSuccessHandler, ale dlaczego używa się tego programu obsługi?
Próbowałem
- wdrożyć pusty sukces obsługi, w wyniku kodu 200 stanu i nadal nie powołując kontroler
- zrobić uwierzytelniania w prosty GenericFilterBean i ustawienie obiektu uwierzytelniania poprzez SecurityContextHolder .getContext(). setAuthentication (authentication), które skutkuje stroną błędu "Bad credentials".
Chciałbym zrozumieć, dlaczego mój kontroler nie jest wywoływana po uwierzytelnieniu tokena. Poza tym, czy istnieje "wiosenny" sposób przechowywania tokena, zamiast przechowywania go w mapie, jak niestandardowa implementacja SecurityContextRepository?
Naprawdę doceniam każdą podpowiedź!
Jakieś działające rozwiązanie dla tego? Mamy ten sam problem i każda wskazówka lub działający kod byłby miły. – tg44