2015-03-06 26 views
15

Dự án của tôi bao gồm hai phần khác nhau, một bảng quản trị JSF và một dịch vụ RESTfull. Tôi đang cố gắng thiết lập bảo mật mùa xuân để sử dụng các phương pháp xác thực khác nhau tùy thuộc vào URL mà người dùng điều hướng.Bảo mật mùa xuân oauth2 và cấu hình đăng nhập mẫu

Các yêu cầu là

  • Người dùng điều hướng đến các trang JSF có được một màn hình đăng nhập, nơi họ xác thực sử dụng xác thực mẫu.
  • Người dùng điều hướng đến dịch vụ REST sử dụng xác thực ngầm OAuth2 với xác thực cơ bản để cấp mã thông báo.

Cấu hình riêng biệt hoạt động, vấn đề là khi tôi cố gắng kết hợp cả hai cấu hình trong một cấu hình, trong trường hợp đó có vẻ như nhà cung cấp REST bị cản trở và xác thực từng yêu cầu ngay cả khi yêu cầu đến url quản trị (điều này được ghi lại từ thứ tự bảo mật mùa xuân).

cấu hình mẫu của tôi là như thể hiện:

  • Đối với hình thức đăng nhập (JSF)

    @Override 
    @Order(1) 
    protected void configure(HttpSecurity http) throws Exception { 
    http 
         .csrf().disable() 
         .authorizeRequests() 
         .antMatchers("/resources/**").permitAll() 
         .antMatchers("/templates/**").permitAll() 
         .antMatchers("/401.html").permitAll() 
         .antMatchers("/404.html").permitAll() 
         .antMatchers("/500.html").permitAll() 
         .antMatchers("/api/**").permitAll() 
         .antMatchers("/ui/admin.xhtml").hasAnyAuthority("admin", "ADMIN") 
         .antMatchers("/thymeleaf").hasAnyAuthority("admin", "ADMIN") 
         //.anyRequest().authenticated() 
         .and() 
         .formLogin() 
         .loginPage("/login") 
         .defaultSuccessUrl("/ui/index.xhtml") 
         .failureUrl("/login?error=1") 
         .permitAll() 
         .and() 
         .logout() 
         .permitAll() 
         .and() 
         .rememberMe() 
         .and().exceptionHandling().accessDeniedPage("/error/403"); 
    
  • OAuth2 an ninh cấu hình (REST) ​​

    @EnableResourceServer 
    @Order(2) 
    public class RestSecurityConfig extends WebSecurityConfigurerAdapter { 
    
        @Inject 
        private UserRepository userRepository; 
    
        @Inject 
        private PasswordEncoder passwordEncoder; 
    
        @Bean 
        ApplicationListener<AbstractAuthorizationEvent> loggerBean() { 
         return new AuthenticationLoggerListener(); 
        } 
    
        @Bean 
        AccessDeniedHandler accessDeniedHandler() { 
         return new AccessDeniedExceptionHandler(); 
        } 
    
        @Bean 
        AuthenticationEntryPoint entryPointBean() { 
         return new UnauthorizedEntryPoint(); 
        } 
    
        /*Override 
        public void configure(WebSecurity web) throws Exception { 
         web.ignoring() 
           .antMatchers(
             "/resources/**" 
             , "/templates/**" 
             , "/login" 
             , "/logout" 
             , "/ui/**" 
             , "/401.html" 
             , "/404.html" 
             , "/500.html" 
           ); 
        }*/ 
    
        @Override 
        protected void configure(HttpSecurity http) throws Exception { 
         ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); 
         if (contentNegotiationStrategy == null) { 
          contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); 
         } 
         MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, 
           MediaType.APPLICATION_FORM_URLENCODED, 
           MediaType.APPLICATION_JSON, 
           MediaType.MULTIPART_FORM_DATA); 
    
         http.authorizeRequests() 
           .antMatchers("/ui/**").permitAll() 
           .and() 
           .anonymous().disable() 
           .sessionManagement() 
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
           .and().httpBasic() 
           .and() 
           .exceptionHandling() 
           .accessDeniedHandler(accessDeniedHandler()) // handle access denied in general (for example comming from @PreAuthorization 
           .authenticationEntryPoint(entryPointBean()) // handle authentication exceptions for unauthorized calls. 
           .defaultAuthenticationEntryPointFor(entryPointBean(), preferredMatcher) 
           .and() 
           .authorizeRequests() 
           .antMatchers("/api/**").fullyAuthenticated(); 
    
        } 
    
        @Override 
        @Bean 
        public AuthenticationManager authenticationManagerBean() throws Exception { 
         return super.authenticationManagerBean(); 
        } 
    
        @Override 
        protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
         auth.userDetailsService(new UserDetailsService() { 
          @Override 
          public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { 
           User user = userRepository.findOneByUsername(s); 
    
           if (null == user) { 
            // leave that to be handled by log listener 
            throw new UsernameNotFoundException("The user with email " + s + " was not found"); 
           } 
    
           return (UserDetails) user; 
          } 
         }).passwordEncoder(passwordEncoder); 
        } 
    
    
        @Configuration 
        @EnableAuthorizationServer 
        protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { 
    
    
    
         @Autowired 
         private AuthenticationManager authenticationManager; 
    
    
         @Bean 
         public JwtAccessTokenConverter accessTokenConverter() { 
          return new JwtAccessTokenConverter(); 
         } 
    
         @Override 
         public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
          oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')"); 
         } 
    
         @Override 
         public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
          endpoints.authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter()); 
         } 
    
    
         @Override 
         public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
          clients.inMemory() 
            .withClient("xxx") 
            .resourceIds(xxx) 
            .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") 
            .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") 
            .scopes("read", "write", "trust", "update") 
            .accessTokenValiditySeconds(xxx) 
            .refreshTokenValiditySeconds(xxx) 
            .secret("xxx") 
    
         } 
        } 
    } 
    

Những cấu hình tồn tại trên dif các lớp ferent và thứ tự được đặt theo cách thủ công.

Có bất kỳ giải pháp nào cho vấn đề này không?

Tốt nhất,

+0

Were Bạn có thể khắc phục vấn đề này? Bạn có thể đăng câu trả lời được không. –

+0

@Maleenc tiếc là không, tôi thực sự sẽ đánh giá cao và trả lời từ những người bảo mật mùa xuân. – maxsap

Trả lời

16

Tôi đã cố gắng điều chỉnh cấu hình bảo mật của bạn. Rất tiếc, tôi không thể xác thực cấu hình này do thiếu ứng dụng tham chiếu.

Có lẽ nó có thể giúp bạn:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserRepository userRepository; 

    @Autowired 
    private PasswordEncoder passwordEncoder; 

    @Autowired 
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(new UserDetailsService() { 
      @Override 
      public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { 
       User user = userRepository.findOneByUsername(s); 

       if (null == user) { 
        throw new UsernameNotFoundException("The user with email " + s + " was not found"); 
       } 

       return (UserDetails) user; 
      } 
     }).passwordEncoder(passwordEncoder); 
    } 

    @Override 
    public void configure(WebSecurity webSecurity) throws Exception { 
     webSecurity 
       .ignoring() 
       .antMatchers("/resources/**" 
         , "/templates/**" 
         , "/login" 
         , "/logout" 
         , "/ui/**" 
         , "/401.html" 
         , "/404.html" 
         , "/500.html"); 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    public static class OAuth2Configuration extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private AuthenticationManager authenticationManager; 

     @Bean 
     public JwtAccessTokenConverter accessTokenConverter() { 
      return new JwtAccessTokenConverter(); 
     } 

     @Override 
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
      oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')"); 
     } 

     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints.authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter()); 
     } 


     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.inMemory() 
        .withClient("xxx") 
        .resourceIds("xxx") 
        .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") 
        .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") 
        .scopes("read", "write", "trust", "update") 
        .accessTokenValiditySeconds(xxx) 
        .refreshTokenValiditySeconds(xxx) 
        .secret("xxx"); 

     } 
    } 

    @Configuration 
    @Order(1) 
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      http 
        .csrf().disable() 
        .authorizeRequests() 
        .antMatchers("/ui/admin.xhtml").hasAnyAuthority("admin", "ADMIN") 
        .antMatchers("/thymeleaf").hasAnyAuthority("admin", "ADMIN") 
        .and() 
        .formLogin() 
        .loginPage("/login") 
        .defaultSuccessUrl("/ui/index.xhtml") 
        .failureUrl("/login?error=1") 
        .permitAll() 
        .and() 
        .logout() 
        .permitAll() 
        .and() 
        .rememberMe() 
        .and().exceptionHandling().accessDeniedPage("/error/403"); 
     } 
    } 

    @Order(2) 
    @Configuration 
    @EnableResourceServer 
    public static class CustomResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter { 

     @Bean 
     ApplicationListener<AbstractAuthorizationEvent> loggerBean() { 
      return new AuthenticationLoggerListener(); 
     } 

     @Bean 
     AccessDeniedHandler accessDeniedHandler() { 
      return new AccessDeniedExceptionHandler(); 
     } 

     @Bean 
     AuthenticationEntryPoint entryPointBean() { 
      return new UnauthorizedEntryPoint(); 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); 
      if (contentNegotiationStrategy == null) { 
       contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); 
      } 
      MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, 
        MediaType.APPLICATION_FORM_URLENCODED, 
        MediaType.APPLICATION_JSON, 
        MediaType.MULTIPART_FORM_DATA); 

      http.authorizeRequests() 
        .and() 
        .anonymous().disable() 
        .sessionManagement() 
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
        .and().httpBasic() 
        .and() 
        .exceptionHandling() 
        .accessDeniedHandler(accessDeniedHandler()) // handle access denied in general (for example comming from @PreAuthorization 
        .authenticationEntryPoint(entryPointBean()) // handle authentication exceptions for unauthorized calls. 
        .defaultAuthenticationEntryPointFor(entryPointBean(), preferredMatcher) 
        .and() 
        .authorizeRequests() 
        .antMatchers("/api/**").fullyAuthenticated(); 
     } 
    } 
} 
+0

Tôi có thể sử dụng formLogin với/** và sử dụng một biểu mẫu đăng nhập khác với/api/** không? Không phải hải quan hóa formLogin của riêng bạn những gì bạn làm ở trên. – WhiteWater

Các vấn đề liên quan