2

こんにちは、OAuth2 で Spring アプリを実装しています。

spring documentationによると、OAuth2 認証でリソース リクエストを有効にするには、@EnableResourceServer アノテーションを追加して OAuth2AuthenticationProcessingFilter を含める必要があります。

このアノテーションを追加しましたが、残念ながら起動時にフィルターがチェーンで呼び出されません。

curl コマンドでアクセス トークンを取得できます。

curl -X POST -H "Authorization: Basic **************************" -v -H "Accept: application/json" -d "username=my.user&password=pass&client_id=my.user&client_secret=4e1d635a-7c9d-426b-a942-cc166438f996&grant_type=password&scope=read write" http://localhost:8080/oauth/token

ただし、リソースは次を要求します。

curl -v -H "Authorization : Bearer ecfa5bfb-c224-4b4a-abf4-cb4a828c2efb" -H "Accept: application/json" http://localhost:8443/oauth/api/meetings/9

与えます:

サーバーからの空の返信

ホスト localhost への接続 #0 はそのまま残されます

私のリソース構成の下:

@Configuration
@EnableWebSecurity
@ComponentScan("com.springapp.mvc")
@EnableResourceServer
@Order(4)
public class Oauth2ResourcesConfigurationAdapter extends ResourceServerConfigurerAdapter {

@Autowired
private OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint;

@Autowired
private PreAuthUserDetailsService preAuthUserDetailsService;

@Autowired
private OAuth2AccessDeniedHandler accessDeniedHandler;

@Autowired
private DefaultTokenServices tokenServices;

@Autowired
private TokenStore tokenStore;

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/oauth/api/**")
            .access("#oauth2.hasScope('read') and #oauth2.hasScope('write') and #oauth2.hasAnyRole('ROLE_USER','ROLE_ADMIN')")
            .accessDecisionManager(accessDecisionManager())
            .anyRequest()
            .fullyAuthenticated();
    http
            .anonymous()
            .disable();
    http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER);
    http
            .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler);
    http
            .logout()
            .logoutUrl("/oauth/logout")
            .logoutSuccessHandler(logoutSuccessHandler())
            .invalidateHttpSession(true);
    http
            .requiresChannel()
            .antMatchers("/oauth/api/**")
            .requiresSecure();
    http
            .portMapper()
            .http(8080)
            .mapsTo(8443);
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources
            .authenticationManager(getAuthenticationManager())
            .tokenServices(tokenServices)
            .tokenStore(tokenStore);
}

private AuthenticationManager getAuthenticationManager() {
    final OAuth2AuthenticationManager oAuth2AuthenticationManager = new OAuth2AuthenticationManager();
    oAuth2AuthenticationManager.setTokenServices(tokenServices);

    return oAuth2AuthenticationManager;
}

private PreAuthenticatedAuthenticationProvider preAuthAuthenticationProvider() {
    final PreAuthenticatedAuthenticationProvider preAuthAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthAuthenticationProvider.setPreAuthenticatedUserDetailsService(preAuthUserDetailsService);

    return preAuthAuthenticationProvider;
}

private AccessDecisionManager accessDecisionManager() {
    return new UnanimousBased(Arrays.<AccessDecisionVoter>asList(new ScopeVoter(),
                                                                 new AuthenticatedVoter(),
                                                                 new WebExpressionVoter()));
}

private LogoutSuccessHandler logoutSuccessHandler() {
    return new OAuth2SuccessLogoutHandler(tokenStore);
}

static final class OAuth2SuccessLogoutHandler implements LogoutSuccessHandler {

    private final TokenStore tokenStore;

    public OAuth2SuccessLogoutHandler(final TokenStore tokenStore) {
        this.tokenStore = tokenStore;
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
           request.toString();
    }
}

}

私の質問は次のとおりです。間違いはどこですか?

4

2 に答える 2

5

authenticationManager Bean を確認する必要があります。次に、ResourceServer セキュリティ設定で Authorization ヘッダーまたは access_token リクエスト パラメータを含むリクエストを検出します。

以下は実際の構成です。これが役立つことを願っています

@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
protected static class ResourceConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${sso.url}")
    private String ssoUrl;

    @Autowired
    private  RedisConnectionFactory redisConnectionFactory;

    @Bean
    protected TokenStore tokenStore() {
        return new RedisTokenStore(redisConnectionFactory);
    }

    @Bean
    @Primary
    protected ResourceServerTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);

        return defaultTokenServices;
    }


    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
        authenticationManager.setTokenServices(tokenServices());
        return authenticationManager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {      
        http.requestMatchers()
        .and().authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers(HttpMethod.GET, "/static/**").permitAll()
            .antMatchers(HttpMethod.GET, "/profile/**").permitAll()
            .antMatchers(HttpMethod.GET, "/services/**").permitAll()
            .anyRequest().authenticated()
        .and().logout()
                .invalidateHttpSession(true)
                .logoutSuccessUrl(ssoUrl+"/logout")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .deleteCookies("JSESSIONID").invalidateHttpSession(true)
                .permitAll();
    }

}

@Configuration
@EnableResourceServer
@Order(1)
protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {



    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("resource-id");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new OAuthRequestedMatcher())
            .authorizeRequests().anyRequest().fullyAuthenticated();

    }
}

private static class OAuthRequestedMatcher implements RequestMatcher {
    public boolean matches(HttpServletRequest request) {
        String auth = request.getHeader("Authorization");
        boolean haveOauth2Token = (auth != null) && auth.startsWith("Bearer");
        boolean haveAccessToken = request.getParameter("access_token")!=null;
        return haveOauth2Token || haveAccessToken;
    }
}
于 2018-07-25T07:52:32.807 に答える
4

では、Spring の初心者向けのアドバイスを次に示します。

FilterChainProxy クラスがあり、それがどのように機能するかを知っておく価値があります。一般に、すべての今後のリクエストは、標準のフィルターと追加のフィルター (構成で追加) によってフィルター処理されます。

すべての WebSecurityConfigurerAdapter には適切な順序が必要であり、この順序に従って、リクエストは適切なリクエスト マッチャーにバインドされます。

リクエストマッチャーは、リクエストを処理するフィルターを提供します。

私の問題は、AnyRequestMatcherを注文する不適切な WebAdapters が原因で、望ましくない動作である私の要求を処理したことでした。適切なリクエスト マッチャーはさらに先の位置にありました。

WebAdapters の順序を変更すると、すべてが修正されました。

乾杯

于 2014-06-11T15:36:34.527 に答える