2016-10-29 7 views
0

私はスプリングブートアプリケーションを持っています。私は、システム内の2つの異なるユーザーセットに対して2つのログインページを持っています。スプリングブート:2つのURLの2つの異なるログインページ

  1. /expertで始まるURL、ユーザーはEXPERTADMINのいずれかの役割を持っている必要があります。ユーザーはフォームログインを使用してシステムにログインし、ログインページパスは/loginです。

  2. cssjsなど一部のURLでは、認証が不要です。

  3. 他のすべてのURLでは、ユーザーは特別な役割を必要とせず、認証で十分です。ユーザーのログインページは/loginTwoである必要があります。

私はこれを実装するためにthis stackoverflowの質問とthisドキュメントを見ました。しかし、/expertを含むURLにアクセスすると、/loginではなく、ログインページ/loginTwoに移動します。ここで

は、以下の私のコードです:

@Autowired 
@Qualifier("userService") 
UserDetailsService userDetailsService; 

@Bean 
public PasswordEncoder passwordEncoder() { 
    PasswordEncoder encoder = new Md5PasswordEncoder(); 
    return encoder; 
} 

@Autowired 
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 
} 

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

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 

     http 
      .authorizeRequests() 
       .antMatchers("/login/**").permitAll(); 
     http 
      .antMatcher("/expert/**") 
      .authorizeRequests() 
       .anyRequest().access("hasRole('ROLE_ADMIN') or hasRole('ROLE_EXPERT')") 
       .and() 
      .formLogin() 
       .loginPage("/login").permitAll(); 
    } 
} 

@Configuration 
public static class StudentWebSecurity extends WebSecurityConfigurerAdapter{ 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     System.out.println("Here in stu"); 

     http 
      .authorizeRequests() 
       .antMatchers("/css/**,/js/**").permitAll() 
       .antMatchers("/error/**").permitAll() 
       .antMatchers("/student/**").permitAll() 
       .antMatchers("/filter/**").permitAll() 
       .antMatchers("/loginTwo").permitAll() 
       .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_EXPERT')") 
       .antMatchers("/").permitAll() 
       .anyRequest().authenticated() 
       .and() 
      .csrf(); 
     http 
      .formLogin() 
       .loginPage("/loginTwo").permitAll() 
       .and() 
      .logout().permitAll(); 
     http 
      .sessionManagement() 
       .maximumSessions(20) 
       .expiredUrl("/loginTwo") 
       .maxSessionsPreventsLogin(false); 
     http 
      .headers().addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)); 
    } 
} 

はこれで私を助けるためにあなたを要求します。

答えて

0

異なるエンドポイントごとに異なる認証フィルタを追加する必要があります。

HttpSecurityのためには、コンストラクタごUserDetailsServiceを与え、同様の認証マネージャを渡して、このような何かを定義することができます:フィルタ用の

.addFilterBefore(new FirstLoginFilter("/api/login/first", userDetailsService, authenticationManager()), UsernamePasswordAuthenticationFilter.class) 
    .addFilterBefore(new SecondLoginFilter("/api/login/second", userDetailsService, authenticationManager()), UsernamePasswordAuthenticationFilter.class) 
    .addFilterBefore(new AdminLoginFilter("/api/login/admin", userDetailsService, authenticationManager()), UsernamePasswordAuthenticationFilter.class) 

実装は次のようになります。

は、上記のすべてのもののために親である抽象認証フィルタで始まるのをしてみましょう:

public abstract class LoginFilter extends AbstractAuthenticationProcessingFilter { 
    protected final SimpleUserDetailsService userService; 

    public LoginFilter(String pattern, SimpleUserDetailsService userService, AuthenticationManager authManager) { 
     super(new AntPathRequestMatcher(pattern)); 
     this.userService = userService; 
     this.setAuthenticationManager(authManager); 
     this.setAuthenticationSuccessHandler(new FormAuthenticationSuccessHandler()); 
     this.setAuthenticationFailureHandler(new FormAuthenticationFailureHandler()); 
    } 

    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws ServletException { 
     User authenticatedUser = this.userService.loadUserByUsername(authentication.getName()); 
     UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser); 
     SecurityContextHolder.getContext().setAuthentication(userAuthentication); 
    } 
} 

そして、実際のフィルタの実装の一例について:

public class FirstLoginFilter extends LoginFilter { 
    public FirstLoginFilter(String pattern, SimpleUserDetailsService userDetailsService, AuthenticationManager authManager) { 
     super(pattern, userDetailsService, authManager); 
    } 

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { 
     User user = (User)(new ObjectMapper()).readValue(request.getInputStream(), User.class); 
     UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()); 
     Authentication authentication = this.getAuthenticationManager().authenticate(loginToken); 
     if(!Role.isRolePresent(authentication.getAuthorities(), Role.YOUR_ROLE)) { 
      throw new BadCredentialsException("Bad credentials"); 
     } else { 
      return authentication; 
     } 
    } 
} 

私の例では、ステートレス認証を使用していますメカニズムのため、それに応じてフィルタを変更する必要があります。あなたの最初の例から分かるように、代わりにセッションを使用しているので、実際にはSpring Securityに組み込まれているので、はるかに簡単です。

関連する問題