0

Spring REST oAuth2 構成に問題があります。Springs は URL を認識してマップしますが、oauth2 セキュリティ チェック (成功) の後に、一致する URL がありません。しかし、Spring はアプリの初期化時にそれを認識しているため、その理由はわかりません。/oauth/token で適切に認証し、トークンを生成できます。トークンによる承認を必要としないリクエストを処理できません。

春 4.0.6、春セキュリティ 3.2.4、春セキュリティ oauth2 2.0.1

コンテキストの初期化からのログ

2014-08-29 08:56:26.415 [Scanner-1] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/{email}],methods=[PUT],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.update(java.lang.String)
2014-08-29 08:56:26.416 [Scanner-1] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/{email}],methods=[DELETE],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.delete(java.lang.String)
2014-08-29 08:56:26.416 [Scanner-1] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/logout],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.logout()
2014-08-29 08:56:26.416 [Scanner-1] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity<java.lang.Void>> com.example.user.UserCommandsController.signup(java.lang.String,java.lang.String)

リクエスト送信後

2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/api/users'; against '/api/users'
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /api/users; Attributes: [permitAll]
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.a.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@31b7d21c, returned: 1
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.web.FilterChainProxy - /api/users reached end of additional filter chain; proceeding with original chain
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcher' processing POST request for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /api/users
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Looking up handler method for path /api/users
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Did not find handler method for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] WARN  o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/api/users] in DispatcherServlet with name 'dispatcher'

そして構成

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

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

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
            .requestMatchers()
            .antMatchers(HttpMethod.POST, "/api/buildings/**")
            .antMatchers(HttpMethod.DELETE, "/api/**")
            .antMatchers(HttpMethod.PATCH, "/api/**")
            .antMatchers(HttpMethod.PUT, "/api/**")
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.POST, "/api/buildings/**").access("hasRole('ROLE_USER')")
            .antMatchers(HttpMethod.DELETE, "/api/**").access("hasRole('ROLE_USER')")
            .antMatchers(HttpMethod.PATCH, "/api/**").access("hasRole('ROLE_USER')")
            .antMatchers(HttpMethod.PUT, "/api/**").access("hasRole('ROLE_USER')");
    }
}



@Controller
@EnableWebSecurity
@Profile("default")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * By default all request need authentication. Only those which do not need it, shall be specified explicitly.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
            .csrf().disable();
        http
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/api/buildings/**").permitAll()//to consider anonymous()
            .antMatchers(HttpMethod.POST, "/api/users").permitAll()//to consider anonymous()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated();
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/app/**","/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals");
    }

    @Override
    @Bean(name = "authenticationManagerBean")
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

ユーザーコントローラーの一部

@RestController
@RequestMapping("/api")
public class UserCommandsController {

    private final UserService userService;
    private AccountRecoveryMailer accountRecoveryMailer;
    private MessageSource messageSource;

    @Inject
    public UserCommandsController(final UserService userService, final AccountRecoveryMailer accountRecoveryMailer,
        final MessageSource messageSource) {
        this.userService = userService;
        this.accountRecoveryMailer = accountRecoveryMailer;
        this.messageSource = messageSource;
    }

    @RequestMapping(value = "/users", method = RequestMethod.POST)
    public Callable<ResponseEntity<Void>> signup(@RequestParam String email, @RequestParam String password) {
        return () -> {
            //do something
           };
    }
}

私が達成したいのは、すべてのリクエストを保護し、それらの一部のみが無料でアクセスできるようにすることです (または、client_id に一致する Authorization ヘッダーのみを使用する場合もあります)。

4

2 に答える 2

0

これが私の問題の解決策です。この悪事の根源は、bean の初期化、つまり、bean のスコープにありました。ところで SSL は必要ありません。

以下の設定は間違っています。やみくもにコピー&ペーストしないでください。

2 つの @ ComponentScanクラスがありました。

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = Application.class,
    excludeFilters = @Filter({RestController.class, Controller.class, Service.class, Repository.class, Configuration.class}))
class WebMvcConfig extends WebMvcConfigurationSupport {
    //some code
}

@Configuration
@ComponentScan(basePackageClasses = Application.class)
class ApplicationConfig {
    //some code
}

そしてマイニング WebAppInitialization コード

@Order(2)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{ApplicationConfig.class, DataSourceConfig.class, SecurityConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebMvcConfig.class};
    }

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);

        return new Filter[]{characterEncodingFilter};
    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("defaultHtmlEscape", "true");
        registration.setInitParameter("spring.profiles.active", "default");
    }
}

ご覧のとおり、 WebMvcConfig.classと一部の Bean タイプの除外により、すべてのタイプの Bean を使用したコンポーネント クラス パス スキャン全体が getRootConfigClasses() メソッドで初期化され、getServletConfigClasses ()メソッドで Bean の一部のみが初期化されます。コンポーネントスキャンで。rootContext の Bean はservletContextで使用できるため、Spring ではこれで十分だと思います。そして、Web アプリのインスタンス化のみでした。Spring Security oAuth2 は、コントローラー マッピングを認識していません。

この問題の解決策は、WebMvcConfig のコンポーネント スキャンを取り除き、 getServletConfigClasses()メソッドを次のように変更することでした。

@Override
protected Class<?>[] getServletConfigClasses() {
   return new Class<?>[]{ApplicationConfig.class, WebMvcConfig.class};
}

Spring Bean の熱心なキャッシングのおかげで、すべてがうまくいきます。

于 2014-08-29T15:51:31.200 に答える