首页 文章

spring security oauth2切换用户过滤器

提问于
浏览
1

我想在我的spring-boot应用程序中设置 SwitchUserFilter ,它实现了spring-security-oauth2 . 我已经在我的 WebSecurityConfiguration 中设置了这个过滤器,扩展了 WebSecurityConfigurerAdapter .

登录后,我获取了我的令牌,一个不记名令牌,我使用配置的 endpoints 来切换用户 .

我在IDE中使用debug跟踪代码,显然更新了SecurityContextHolder并注入了新的目标用户 .

但是,当请求被重定向到目标URL(此过滤器的属性)时,SecurityContextHolder会返回旧用户,而不是我请求的内容 .

我已经检查了 OAuth2AuthenticationProcessingFilter 并且从请求中提取的令牌返回了相同的承载令牌,并且使用它来构建用户详细信息并将其注入SecurityContextHolder .

有没有办法用oauth2方法使用这种过滤器?

2 回答

  • 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()
                });
    }
    
  • 0

    您可以注入自己的AuthenticationManager并覆盖该行为

    private class AuthenticationManager extends OAuth2AuthenticationManager {
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
            if (currentAuthentication instanceof UsernamePasswordAuthenticationToken) {
                for (GrantedAuthority ga : currentAuthentication.getAuthorities()) {
                    if (ga instanceof SwitchUserGrantedAuthority) {
                        SwitchUserGrantedAuthority switchedFrom = (SwitchUserGrantedAuthority) ga;
                        Authentication switchedFromSource = switchedFrom.getSource();
                        for (GrantedAuthority sf : switchedFromSource.getAuthorities()) {
                            String authority = sf.getAuthority();
                            if (switchUserAuthority.equals(authority)) {
                                return currentAuthentication;
                            }
                        }
                        break;
                    }
                }
            }
            return super.authenticate(authentication);
        }
    

相关问题