Spring boot oauth2 - как перехватить событие непосредственно перед перенаправлением на клиент с токеном - PullRequest
0 голосов
/ 04 июля 2018

Я разрабатываю загрузочное приложение Spring, следуя его стандартам. Мне было интересно, можно ли перехватить какое-либо событие непосредственно перед перенаправлением на клиента с действительным токеном.

Мне нужно включить в ответ некоторую дополнительную информацию. Это было бы возможно? Спасибо

1 Ответ

0 голосов
/ 04 июля 2018

Чтобы добавить и добавить дополнительную информацию о токене, лучше и стандартнее использовать TokenEnhancer. Это интерфейс, который дает вам возможность улучшить токен доступа перед его сохранением. Ниже приведен пример скелета:

@Configuration
@EnableAuthorizationServer
class SecurityOAuth2AutorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.....
                .tokenEnhancer(tokenEnhancer())
                .approvalStoreDisabled();
    }




    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        ....
    }


    @Bean
    public TokenEnhancer tokenEnhancer(){
        return new YourTokenEnhancer ();
    }
}

class YourTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        User user = (User) authentication.getPrincipal();
        final Map<String, Object> additionalInfo = new HashMap<>();

        additionalInfo.put("yourAdditionalKey", "yourAdditionalValue");

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

        return accessToken;
    }
}

Обновление

учитывая ваше сообщение, если вы хотите добавить информацию в заголовок, вы можете использовать перехватчик и связать его с классом org.springframework.security.oauth2.provider.endpoint.TokenEndpoint, который является классом, который вы вызываете для получения токена и добавления услышать вашу дополнительную информацию.

Однако я не одобряю этот подход в пользу более стандартного способа и рассматриваю возможность использования TokenEnhancer, который является стандартным способом добавления дополнительной информации на ваш токен.

Обновление

учитывая комментарии, которые я могу предложить, чтобы реализовать вашу логику аудита с аспектом на вашем сервере аутентификации, аспект может быть таким, как показано ниже:

@Aspect
@Component
class AuditLogger {

    @AfterReturning("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public void aspect(JoinPoint joinPoint)  {
        Map<String, String> params = (Map<String, String>) joinPoint.getArgs()[1];
        System.out.println("success");
        System.out.println(params);
//        your audit logic in case of successful login
    }

    @AfterThrowing(value = "execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))", throwing = "error")
    public void error(JoinPoint joinPoint, Exception error) {
        System.out.println(error);
        Map<String, String> params = (Map<String, String>) joinPoint.getArgs()[1];
        System.out.println("error");
        System.out.println(params);
//        your audit logic in case of failure login
    }

}

Я предлагаю использовать аспект вместо реализации пользовательских компонентов Spring Security, потому что: во-первых, аудит является сквозной задачей, и аспект является одним из лучших решений для достижения этой цели, а затем, потому что настраивайте Spring Security, особенно для Oauth2 - это сложная задача, и я не советую ее, поскольку мой опыт слишком сложен, и усилия не окупаются, протокол очень сложен, и заполнить все варианты использования - задача. С аспектом, который делает аудит для вас в правильной точке, это лучший вариант для вас.

Я построил аспект, который выполняет аудит по методу TokenEndpoint.postAccessToken, то есть коду безопасности Spring oAuht2, который генерирует токен

Код вашего интереса к платформе Spring ниже:

@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {

    ....

    @RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
    public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
            Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {

        if (!(principal instanceof Authentication)) {
            throw new InsufficientAuthenticationException(
                    "There is no client authentication. Try adding an appropriate authentication filter.");
        }

        String clientId = getClientId(principal);
        ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);

        TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);

        if (clientId != null && !clientId.equals("")) {
            // Only validate the client details if a client authenticated during this
            // request.
            if (!clientId.equals(tokenRequest.getClientId())) {
                // double check to make sure that the client ID in the token request is the same as that in the
                // authenticated client
                throw new InvalidClientException("Given client ID does not match authenticated client");
            }
        }
        if (authenticatedClient != null) {
            oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
        }
        if (!StringUtils.hasText(tokenRequest.getGrantType())) {
            throw new InvalidRequestException("Missing grant type");
        }
        if (tokenRequest.getGrantType().equals("implicit")) {
            throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
        }

        if (isAuthCodeRequest(parameters)) {
            // The scope was requested or determined during the authorization step
            if (!tokenRequest.getScope().isEmpty()) {
                logger.debug("Clearing scope of incoming token request");
                tokenRequest.setScope(Collections.<String> emptySet());
            }
        }

        if (isRefreshTokenRequest(parameters)) {
            // A refresh token has its own default scopes, so we should ignore any added by the factory here.
            tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
        }

        OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
        if (token == null) {
            throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
        }

        return getResponse(token);

    }

    ....
}

Я надеюсь, что это может помочь вам

...