2016-07-30 69 views
0

我想建立在我的春天啓動的應用程序SwitchUserFilter它實現了彈簧安全的oauth2呢。我已經設置了此過濾器在我WebSecurityConfiguration延伸WebSecurityConfigurerAdapter春季安全的oauth2 +交換機用戶過濾

登錄後,我獲得我的令牌,不記名令牌,並使用配置的端點切換用戶。

我跟着我的IDE中的調試代碼,顯然SecurityContextHolder已更新,並注入一個新的目標用戶。

但是,當請求被重定向到目標URL(此過濾器的屬性)時,SecurityContextHolder將舊用戶退回給我,而不是我所請求的。

我已經檢查OAuth2AuthenticationProcessingFilter和從請求中提取的令牌返回一個相同的承載的令牌和與此它建立用戶的細節和它注入到SecurityContextHolder中

有什麼辦法可以用oauth2方法來使用這種過濾器嗎?

回答

1

問題是您需要創建一個包含新目標用戶信息的新令牌。這個新的令牌必須被髮送回客戶端,所以爲了將來的請求使用新的目標用戶令牌。在我們的例子中,令牌在服務器端持久存在(使用JDBCTokenStore),但它也可以在完全服務器端的無狀態環境(JWT-Token)中運行。

我們的環境是一個帶角度爲1.2的客戶端的spring-boot/jhipster應用程序。

創建一個新的令牌:

@Inject 
private UserDetailsService userDetailsService; 

@Inject 
private AuthorizationServerTokenServices tokenService; 

@Inject 
private ClientDetailsService clientDetailsService; 


    public OAuth2AccessToken createImpersonationAccessToken(String login) { 
     UserDetails userDetails = userDetailsService.loadUserByUsername(login); 
     log.info("Switching current user to {}", login); 

     Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities(); 
     List<GrantedAuthority> impersonationAuthorities = new ArrayList<>(authorities); 
     Authentication source = SecurityContextHolder.getContext().getAuthentication(); 
     // add current user authentication (to switch back from impersonation): 
     SwitchUserGrantedAuthority switchUserAuthority = 
       new SwitchUserGrantedAuthority(AuthoritiesConstants.IMPERSONATION, source); 
     impersonationAuthorities.add(switchUserAuthority); 
        UserDetails newUserDetails = 
       org.springframework.security.core.userdetails.User 
       .withUsername(login) 
       .authorities(impersonationAuthorities) 
       .password("justinventedhere") 
       .build(); 
          Authentication userPasswordAuthentiation = 
       new UsernamePasswordAuthenticationToken(newUserDetails, null, impersonationAuthorities); 

     Map<String, String> parameters = new HashMap<>();   
     ClientDetails client = clientDetailsService.loadClientByClientId(clientId); 
        OAuth2Request oauthRequest = new OAuth2Request(parameters, client.getClientId(), client.getAuthorities(), true, 
       client.getScope(), client.getResourceIds(), null, null, null); 
     OAuth2Authentication authentication = new OAuth2Authentication(oauthRequest, userPasswordAuthentiation); 
     OAuth2AccessToken createAccessToken = tokenService.createAccessToken(authentication); 
        return createAccessToken; 
    } 

這個新的令牌返回給客戶端(在本例中的角1.2應用程序)存儲在其本地存儲的令牌(在下次請求中使用)。然後,應用程序需要重新加載(更新目標用戶的最簡單方式):

vm.switchToClient = function (client) { 
    vm.switchingUser = true; 
    UserService.switchToClient(client, function(response) { 
       var expiredAt = new Date(); 
       $localStorage.authenticationToken = response; 
       window.location.href='#/'; 
       window.location.reload() 
      }); 
}