Spring Bootアプリケーションにセキュリティを追加しようとしています。現在のアプリケーションはRESTコントローラを使用しており、GET
またはPOST
リクエストを受け取るたびに、HTTPヘッダーを読み取ってユーザーとパスワードを取得し、すべてのユーザーを保存しているプロパティファイルに対してそれらを検証します。これをSpring Securityを使用するように変更したいと思います。
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/index.html").permitAll()
.antMatchers("/swagger-ui.html").hasRole("ADMIN")
.anyRequest().authenticated();
}
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("admin").password("password").roles("ADMIN").build());
}
}
configure
メソッドに、ユーザー認証情報がログインフォームではなくヘッダーから取得されることをどのように伝えることができますか?
デフォルトのorg.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
は、クライアントから提供されたユーザー名とパスワードをリクエストのパラメーターから取得し、実際にはヘッダーから取得する必要があるため、使用しないでください。
したがって、カスタムAuthenticationFilter
拡張参照UsernamePasswordAuthenticationFilter
を記述して、要件に合わせて動作を変更する必要があります。
public class HeaderUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
/**
*
*/
public HeaderUsernamePasswordAuthenticationFilter() {
super();
this.setFilterProcessesUrl("/**");
this.setPostOnly(false);
}
/* (non-Javadoc)
* @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainPassword(javax.servlet.http.HttpServletRequest)
*/
@Override
protected String obtainPassword(HttpServletRequest request) {
return request.getHeader(this.getPasswordParameter());
}
/* (non-Javadoc)
* @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainUsername(javax.servlet.http.HttpServletRequest)
*/
@Override
protected String obtainUsername(HttpServletRequest request) {
return request.getHeader(this.getPasswordParameter());
}
}
このフィルターの例は、org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
を拡張してすべてのリクエストをリッスンし、username
ではなくpassword
およびparameters
をヘッダーから取得します。
次に、この方法で構成を変更し、UsernamePasswordAuthenticationFilter
位置にフィルターを設定します。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAt(
new HeaderUsernamePasswordAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/index.html").permitAll()
.antMatchers("/swagger-ui.html").hasRole("ADMIN")
.anyRequest().authenticated();
}
メモリ内認証はあなたの目的に役立ちます
@Configuration
@EnableWebMvc
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password("password1").roles("USER")
.and()
.withUser("user2").password("password2").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
}
}
最小限のコードの追加は、フィルターを定義してそれをセキュリティ構成に追加することです。
XHeaderAuthenticationFilter.Java
@Component
public class XHeaderAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String xAuth = request.getHeader("X-Authorization");
User user = findByToken(xAuth);
if (user == null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token invalid");
} else {
final UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
}
//need to implement db user validation...
private User findByToken(String token) {
if (!token.equals("1234"))
return null;
final User user = new User(
"username",
"password",
true,
true,
true,
true,
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
return user;
}
}
SecurityConfig.Java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.addFilterBefore(new XHeaderAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
別のアプローチは、SpringのAOP
を使用して、注釈付きコントローラーメソッドに入る前に実行するロジックの注釈を定義することです。