最新のSpringブート、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への要求に有効なトークンを追加しています"(これはJsonを返すRESTコントローラです)。フィルタとプロバイダの両方が呼び出されます。 問題はです。ブラウザは、RESTコントローラの要求されたメソッドを呼び出す代わりに、 "/"にリダイレクトされます。これはSavedRequestAwareAuthenticationSuccessHandlerで発生するようですが、なぜこのハンドラが使用されていますか?
私は200のステータスコードで、その結果、空の成功ハンドラを実装するために
- を試してみましたが、まだ簡単なGenericFilterBeanで認証を行うために
- コントローラを呼び出し、SecurityContextHolderを介して認証オブジェクトを設定しません.getContext()。 "不正な資格情報"エラーページをもたらすsetAuthentication(認証)。
トークンを認証した後にコントローラが呼び出されない理由を理解したいと思います。それ以外に、トークンをMapに格納するのではなく、SecurityContextRepositoryのカスタム実装のように「春」の方法がありますか?
本当にありがとうございます。
これに対応する解決策はありますか?私たちは同じ問題を抱えています。ヒントや作業コードは素晴らしいでしょう。 – tg44