2017-05-18 13 views
-1

彼ら二人は、学校やボランティアは、それぞれが独自のUserDetailsの実装を持つがあるセキュリティコンテキスト、およびUserDetailsS​​ervice実装は、また、それぞれが異なるHTTP構成を持っています学校春のセキュリティを使用間違った私は、ユーザーの2種類があり

protected void configure(HttpSecurity http) throws Exception { 
     http 
       .antMatcher("/school/**") 
       .userDetailsService(service) 
       .formLogin().loginPage("/school/login").permitAll().usernameParameter("username") 
       .passwordParameter("password").failureUrl("/school/login?error=true") 
       .and() 
       .authorizeRequests() 
       .antMatchers("/school/register").permitAll() 
       .antMatchers("/school/confirm**").permitAll() 
       .antMatchers("/school/**").hasRole(School.class.getSimpleName()) 
       .and() 
       .rememberMe().tokenValiditySeconds(2592000).rememberMeParameter("remember-me") 
       .userDetailsService(service).key("S").rememberMeCookieName("S") 
       .and() 
       .logout().logoutSuccessUrl("/").logoutUrl("/school/logout"); 
    } 

のためのものであり、この1つは、両方のserviceでボランティア

protected void configure(HttpSecurity http) throws Exception { 
      http 
        .antMatcher("/volunteer/**") 
        .userDetailsService(service) 
        .formLogin().loginPage("/volunteer/login").permitAll().usernameParameter("username") 
        .passwordParameter("password").failureUrl("/volunteer/login?error=true") 
        .and() 
        .authorizeRequests() 
        .antMatchers("/volunteer/register").permitAll() 
        .antMatchers("/volunteer/confirm**").permitAll() 
        .antMatchers("/volunteer/**").hasRole(Volunteer.class.getSimpleName()) 
        .and() 
        .rememberMe().tokenValiditySeconds(2592000).rememberMeParameter("remember-me") 
        .userDetailsService(service).key("V").rememberMeCookieName("V") 
        .and() 
        .logout().logoutSuccessUrl("/").logoutUrl("/volunteer/logout"); 
     } 

のためであることは、ユーザーの詳細ですサービス実装 これらは、WebSecurityConfigurerAdapterを拡張する2つのネストされたクラスで構成されています。 私の問題は、私が学校にログインしてから(例えば)http://localhost/volunteerに行くと、ログインフォームの代わりに禁止された403が表示されることです。 私はデバッグを有効にして、セキュリティコンテキストで認証されたユーザーを見つけて使用しているのを見ましたが、それは403で失敗する必要な役割はありませんが、ボランティアとログイン用のログインページに明示的に行くと、私はセクションをボランティアに行くときに

17:11:50.628 [http-nio-8081-exec-9] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/school/login'; against '/volunteer/**' 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/school/login'; against '/school/**' 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.context.HttpSessionSecurityContextRepository: HttpSession returned null object for SPRING_SECURITY_CONTEXT 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.context.HttpSessionSecurityContextRepository: No SecurityContext was available from the HttpSession: [email protected] A new one will be created. 
17:11:50.629 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 3 of 15 in additional filter chain; firing Filter: 'HeaderWriterFilter' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.header.writers.HstsHeaderWriter: Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]19d9486b 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 4 of 15 in additional filter chain; firing Filter: 'CharacterEncodingFilter' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 5 of 15 in additional filter chain; firing Filter: 'CsrfFilter' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 6 of 15 in additional filter chain; firing Filter: 'LogoutFilter' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/school/login'; against '/school/logout' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.FilterChainProxy: /school/login at position 7 of 15 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/school/login'; against '/school/login' 
17:11:50.630 [http-nio-8081-exec-9] DEBUG security.web.authentication.UsernamePasswordAuthenticationFilter: Request is to process authentication 

そして:学校としてログインの

これ等:ここでは同じ403と学校としてログインはログです

17:15:03.860 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/volunteer'; against '/volunteer/**' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.context.HttpSessionSecurityContextRepository: Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: '[email protected]5de31c: Authentication: org.springframew[email protected]b35de31c: Principal: [email protected]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EC164B454F5406F933CCB3C6CFEF2E1D; Granted Authorities: ROLE_School' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 3 of 15 in additional filter chain; firing Filter: 'HeaderWriterFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.header.writers.HstsHeaderWriter: Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]439cf926 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 4 of 15 in additional filter chain; firing Filter: 'CharacterEncodingFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 5 of 15 in additional filter chain; firing Filter: 'CsrfFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 6 of 15 in additional filter chain; firing Filter: 'LogoutFilter' 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Request 'GET /volunteer' doesn't match 'POST /volunteer/logout 
17:15:03.861 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 7 of 15 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Request 'GET /volunteer' doesn't match 'POST /volunteer/login 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 8 of 15 in additional filter chain; firing Filter: 'BasicAuthenticationFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 9 of 15 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 10 of 15 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 11 of 15 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.authentication.rememberme.RememberMeAuthenticationFilter: SecurityContextHolder not populated with remember-me token, as it already contained: 'org.springframew[email protected]b35de31c: Principal: [email protected]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EC164B454F5406F933CCB3C6CFEF2E1D; Granted Authorities: ROLE_School' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 12 of 15 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.authentication.AnonymousAuthenticationFilter: SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframew[email protected]b35de31c: Principal: [email protected]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EC164B454F5406F933CCB3C6CFEF2E1D; Granted Authorities: ROLE_School' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 13 of 15 in additional filter chain; firing Filter: 'SessionManagementFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 14 of 15 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.FilterChainProxy: /volunteer at position 15 of 15 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/volunteer'; against '/volunteer/register' 
17:15:03.864 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/volunteer'; against '/volunteer/confirm**' 
17:15:03.865 [http-nio-8081-exec-5] DEBUG security.web.util.matcher.AntPathRequestMatcher: Checking match of request : '/volunteer'; against '/volunteer/**' 
17:15:03.865 [http-nio-8081-exec-5] DEBUG security.web.access.intercept.FilterSecurityInterceptor: Secure object: FilterInvocation: URL: /volunteer; Attributes: [hasRole('ROLE_Volunteer')] 
17:15:03.865 [http-nio-8081-exec-5] DEBUG security.web.access.intercept.FilterSecurityInterceptor: Previously Authenticated: org.springframew[email protected]b35de31c: Principal: [email protected]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EC164B454F5406F933CCB3C6CFEF2E1D; Granted Authorities: ROLE_School 
17:15:03.865 [http-nio-8081-exec-5] DEBUG security.access.vote.AffirmativeBased: Voter: org.sp[email protected]3466a837, returned: -1 
17:15:03.887 [http-nio-8081-exec-5] DEBUG context.support.ReloadableResourceBundleMessageSource: No properties file found for [classpath:localization/messages_en_US] - neither plain properties nor XML 
17:15:03.888 [http-nio-8081-exec-5] DEBUG context.support.ReloadableResourceBundleMessageSource: Re-caching properties for filename [classpath:localization/messages_en] - file hasn't been modified 
17:15:03.889 [http-nio-8081-exec-5] DEBUG context.support.ReloadableResourceBundleMessageSource: No properties file found for [classpath:localization/messages] - neither plain properties nor XML 
17:15:03.890 [http-nio-8081-exec-5] DEBUG security.web.access.ExceptionTranslationFilter: Access is denied (user is not anonymous); delegating to AccessDeniedHandler 

ですそれは春に可能です同時に複数のユーザーとしてログインすることができますか?

もしそうなら、これを達成するには?何らかの形で新しいセキュリティコンテキスト、認証プロバイダなどを作成する必要がありますか?

私がボランティア側にいる場合、なぜ学校のセキュリティコンテキストを使用しますか?別の名前でセッションに/抽出セキュリティコンテキストを記憶するセキュリティ・フィルタ・チェーン

http.addFilterBefore(new MultipleLoginFilter(), SecurityContextPersistenceFilter.class);

春するフィルタを追加することによって解決

+1

1つのアプリケーション、1つのセッションしたがって1セッションコンテキストがあります。アプリケーションのさまざまな部分に異なるセキュリティコンテキストが存在することはありません。 –

+0

@ M.Deinumだから私は2つのタイプのユーザーがある場合、それらが単一のセッションのために同時に認証される方法はありませんか?しかし、私は本当にその非常に一般的なシナリオを信じていますが、この制限を回避するオプションはありませんか? –

+0

Spring Securityインフラストラクチャの大部分を再実装する必要はありません。 Springセッションからマイルを得て、セッション識別子(ヘッダー)としてクッキーとして何かを使用するかもしれません。 –

答えて

0

。反射によって寸法を説明するための 中古注釈:ユーザの詳細実装に注釈を付ける

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface SecurityDimension { 
    String name(); 
} 

public class SimpleLoginInvalidator implements LogoutSuccessHandler { 

private static final Logger logger = LoggerFactory.getLogger(SimpleLoginInvalidator.class); 

@Override 
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
    HttpSession session = request.getSession(); 
    try { 
     String dimensionName = authentication.getPrincipal().getClass().getAnnotation(SecurityDimension.class).name(); 
     session.removeAttribute(dimensionName + "_" + SPRING_SECURITY_CONTEXT_KEY); 
     logger.debug("Cleared security context for dimension: " + dimensionName); 
    } catch (NullPointerException npe) { 
     logger.debug("Could not clear custom security context attribute", npe); 
    } 
} 

}

それはまだ出て「よりを探して、誰かの役に立てば幸い:SimpleLoginInvalidatorがある

http.clearAuthentication(true) .invalidateHttpSession(false).logoutSuccessHandler(new SimpleLoginInvalidator())

:ログアウトを押しただけで、ユーザーを無効にする も設定ログアウトボックスの回答の

MultipleLoginFilter:

public class MultipleLoginFilter extends OncePerRequestFilter { 

private static final Pattern pattern = Pattern.compile("(?<!/)/([^/?#]+)"); 

@Override 
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
    logger.debug("Performing multiple login management"); 
    HttpSession session = request.getSession(false); 

    String path = request.getRequestURI().replace(request.getContextPath(), ""); 
    String desiredDimension = getDesiredDimension(path); 
    logger.debug("Requesting security context for security dimension: " + desiredDimension); 

    SecurityContext context = (SecurityContext) session.getAttribute(SPRING_SECURITY_CONTEXT_KEY); 
    if (context == null) { 
     logger.debug("Current context is empty, trying to find and associate the one stored session..."); 
     populateSecurityContextByDimension(session, desiredDimension); 
    } else { 
     logger.debug("Extracted non-null current security context: " + context); 
     String dimensionName = context.getAuthentication().getPrincipal().getClass().getAnnotation(SecurityDimension.class).name(); 
     if (!path.matches("/" + dimensionName + "(/.+)?")) { 
      logger.debug("Extracted security context is not associated with desired security dimension(" + desiredDimension + "). Storing in session..."); 
      session.setAttribute(dimensionName + "_" + SPRING_SECURITY_CONTEXT_KEY, context); 
      populateSecurityContextByDimension(session, desiredDimension); 
     } else { 
      logger.debug("Current security context is associated with desired security dimension, proceed as default."); 
     } 
    } 
    filterChain.doFilter(request, response); 
} 

private String getDesiredDimension(String requestUrl) { 

    Matcher m = pattern.matcher(requestUrl); 
    String desiredDimension = ""; 
    if (m.find() && m.groupCount() == 1) { 
     desiredDimension = m.group(1); 
    } else { 
     logger.error("Could not identify desired security dimension from url: " + requestUrl); 
    } 
    return desiredDimension; 
} 

private void populateSecurityContextByDimension(HttpSession session, String desiredDimension) { 
    logger.debug("Extracting stored security context associated with desired dimension(" + desiredDimension + ")..."); 
    SecurityContext localContext = (SecurityContext) session.getAttribute(desiredDimension + "_" + SPRING_SECURITY_CONTEXT_KEY); 
    session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, localContext); 
    if(localContext != null) { 
     logger.debug("Storing extracted context as current, context: " + localContext); 
    } else { 
     logger.debug("No security context for dimension(" + desiredDimension + ") in session, assigning null."); 
    } 
} 

}