Spring Security OAuth2 реализует вход в систему и кик

Java

справочная информация

Учетная запись может быть зарегистрирована только в одном месте, и подобные бизнес-требования очень распространены в существующих системах пост-управления. Но в исходном методе токена безопасности oauth2 Spring (так называемый вход в систему) не может удовлетворить аналогичные потребности.

давайте сначала посмотримTokenEndpointпоток методов

Клиент обращается к интерфейсу /oauth/token с параметрами и, наконец, вызываетTokenGranter

TokenGranterВ соответствии с различными типами авторизации получите информацию об аутентификации пользователя и вызовитеTokenServicesсгенерировать токен

Re-TokenService

  • Переписать логику релизаcreateAccessToken, когда токен, управляемый пользователем, существует, он будет удален и создан заново, что приведет к тому, что токен, полученный при предыдущем входе в систему, станет недействительным и будет выжат естественным образом.
	@Transactional
	public OAuth2AccessToken createAccessToken() {   
		OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
		OAuth2RefreshToken refreshToken = null;
		// 重写此处,当用户关联的token 存在时,删除原有令牌
		if (existingAccessToken != null) {
			tokenStore.removeAccessToken(existingAccessToken);
		}
		else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
			ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
			if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
				refreshToken = createRefreshToken(authentication);
			}
		}
	OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
	tokenStore.storeAccessToken(accessToken, authentication);
	// In case it was modified
	refreshToken = accessToken.getRefreshToken();
	if (refreshToken != null) {
		tokenStore.storeRefreshToken(refreshToken, authentication);
	}
	return accessToken;
}
скопировать код

Переписать логику генерации ключа Token

  • Как показано в приведенном выше коде, мы реализуем уникальный логин одного терминала пользователя. Что такое одиночный терминал? Мы можем использовать аналогию входа QQ. Мобильный терминал и терминал ПК могут войти в систему одновременно, но мобильный терминал и мобильный терминал не может одновременно находиться в сети.
  • Как добиться уникального логина на разных клиентах?

Сначала посмотрите на исходный код вышеOAuth2AccessToken existingAccessToken=tokenStore.getAccessToken(authentication);Как судить о существовании токена на основе информации о пользователе?

public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
		String key = authenticationKeyGenerator.extractKey(authentication);
		  // redis 查询逻辑,根据 key
		return accessToken;

}

  • Генератор значений ключа AuthenticationKeyGenerator по умолчанию в соответствии сusername/clientId/scopeКомбинация параметров генерирует уникальный токен
public String extractKey(OAuth2Authentication authentication) {
	Map<String, String> values = new LinkedHashMap<String, String>();
	OAuth2Request authorizationRequest = authentication.getOAuth2Request();
	if (!authentication.isClientOnly()) {
		values.put(USERNAME, authentication.getName());
	}
	values.put(CLIENT_ID, authorizationRequest.getClientId());
	if (authorizationRequest.getScope() != null) {
		values.put(SCOPE, OAuth2Utils.formatParameterList(new TreeSet<String>(authorizationRequest.getScope())));
	}
	return generateKey(values);
}
  • Если вы хотите реализовать уникальный логин нескольких терминалов, вам нужно только разрешить одному и тому же пользователю генерироватьtokenСогласовано, плюс упомянутая выше логика модификации createToken, обе удаленыextractKeyУсловие clientId для clientId не различает терминал
public String extractKey(OAuth2Authentication authentication) {
	Map<String, String> values = new LinkedHashMap<String, String>();
	OAuth2Request authorizationRequest = authentication.getOAuth2Request();
	if (!authentication.isClientOnly()) {
		values.put(USERNAME, authentication.getName());
	}
	if (authorizationRequest.getScope() != null) {
		values.put(SCOPE, OAuth2Utils.formatParameterList(new TreeSet<String>(authorizationRequest.getScope())));
	}
	return generateKey(values);
}
  • Наконец, добавьте новый TokenService на сервер авторизации.