我試圖用最新版本的Spring Boot,Web和安全實現自定義身份驗證邏輯,但我正在努力解決一些問題。我在類似的問題/教程中嘗試了很多解決方案,但沒有成功或理解實際發生的事情。Spring自定義身份驗證過濾器和提供程序不調用控制器方法
我使用無狀態身份驗證創建了一個REST應用程序,即有一個REST端點(/ web/auth/login)需要用戶名和密碼並返回一個字符串標記,然後在所有其他REST端點(/ api/**)來標識用戶。我需要實現一個定製的解決方案,因爲將來認證將變得更加複雜,我想了解Spring Security的基礎知識。
爲了實現令牌認證,我創建一個定製的過濾器,並提供:
過濾器:
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);
}
}
提供者:
@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);
}
}
的配置:
@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應用於供應商(以及在登錄過程):
@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);
}
}
會發生什麼: 我在請求中追加一個有效的標記爲「/ API/BLA 「(這是一個REST控制器返回一些Json)。過濾器和提供者都被調用。 問題是,瀏覽器被重定向到「/」而不是調用REST控制器的請求方法。這似乎發生在SavedRequestAwareAuthenticationSuccessHandler中,但爲什麼使用此處理程序?
我試圖
- 實現空成功處理程序,導致200個狀態碼,但仍不能調用控制器
- 做認證在一個簡單的GenericFilterBean並通過SecurityContextHolder中設置的認證對象.getContext()。setAuthentication(身份驗證)會導致「憑據錯誤」錯誤頁面。
我想了解爲什麼我的控制器不會在我驗證令牌後被調用。除此之外,是否存在一種「Spring」方式來存儲令牌,而不是將其存儲在Map中,就像SecurityContextRepository的自定義實現一樣?
我真的很感激任何提示!
任何工作解決方案?我們有同樣的問題,任何提示或工作代碼都會很好。 – tg44