web-dev-qa-db-ja.com

HTTPヘッダーを使用したSpring Security

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メソッドに、ユーザー認証情報がログインフォームではなくヘッダーから取得されることをどのように伝えることができますか?

6
Chayma Atallah

デフォルトの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();
    }
3
jlumietu

メモリ内認証はあなたの目的に役立ちます

@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();   
    }

}
2
Pete T

最小限のコードの追加は、フィルターを定義してそれをセキュリティ構成に追加することです。

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を使用して、注釈付きコントローラーメソッドに入る前に実行するロジックの注釈を定義することです。

0
shahaf