我想建立SwitchUserFilter中实现弹簧安全的oauth2但我的春天启动的应用程序。我已经设置了我的WebSecurityConfiguration该过滤器扩展WebSecurityConfigurerAdapter。
登录后我得到我的令牌,承载令牌,我用一个配置的端点切换用户。
我按照与调试的代码在我的IDE,显然SecurityContextHolder的更新和新的目标用户被注入。
然而,当请求重定向到目标URL(这个过滤器的属性),SecurityContextHolder中给我的老用户的背部,而不是我所要求的东西。
我已经检查OAuth2AuthenticationProcessingFilter和从请求中提取的令牌返回一个相同的承载的令牌和与此它建立用户的细节和它注入到SecurityContextHolder中。
有没有办法使用这种过滤器的使用方法的oauth2?
问题是,你需要创建一个包含新的目标用户信息的新令牌。这种新的令牌必须发送回客户端,所以对于将来的请求使用新的目标用户令牌。在我们的例子中,令牌坚持在服务器端(使用JDBCTokenStore),但它也将工作完全在服务器端的无状态的环境(JWT令牌)。
我们的环境是具有角度1.2客户端的弹簧引导/ 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()
});
}
你可以注入自己的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);
}