JWTを使用してアプリケーションを保護するために このauth0のチュートリアル をフォローしています。
最終的に次のWebSecurity構成になりました。
@EnableWebSecurity
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final BCryptPasswordEncoder passwordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.and().cors()
.and().csrf()
.disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, REGISTER_URL).permitAll()
.antMatchers(HttpMethod.POST, LOGIN_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
// This disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
および次のJWTAuthenticationFilter:
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
ApplicationUser credentials = new ObjectMapper().readValue(request.getInputStream(), ApplicationUser.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUsername(),
credentials.getPassword(),
new ArrayList<>()
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes())
.compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
現時点では、アプリは/login
URLでPOSTリクエストを受け付けます。URLをたとえば/api/auth/login
に変更する方法はありますか。 URL文字列を認証フィルターに挿入しますか、それともセキュリティ構成で何らかの方法で設定しますか?
拡張しています org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter それ自体が拡張します org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter 。この最後のクラスには、これを行うことを目的としたsetFilterProcessesUrl
というセッターがあります。
setFilterProcessesUrl
public voidsetFilterProcessesUrl(String filterProcessesUrl)
認証が必要かどうかを決定するURLを設定します
パラメーター:filterProcessesUrl
This はそのjavadocセクションへのリンクです
したがって、WebSecurityConfigurerAdapter
では、次のようにすることができます。
@Bean
public JWTAuthenticationFilter getJWTAuthenticationFilter() {
final JWTAuthenticationFilter filter = new JWTAuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/api/auth/login");
return filter;
}
そして、同じクラスのconfigure
メソッドで、新しいインスタンスを作成する代わりに、それを参照するだけです。
.addFilter(getJWTAuthenticationFilter())
少し改善されたのは、カスタムプロセスURLを使用してフィルターを作成し、Beanを作成せずに使用することです。これは、ここ以外では必要ないと思います。
JWTAuthenticationFilter authenticationFilter = new JWTAuthenticationFilter(authenticationManager());
authenticationFilter.setFilterProcessesUrl("/mobile/login");
....
.and()
.addFilter(authenticationFilter)
.addFilter(new JWTAuthenticationFilter(authenticationManager()))