Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре (3)

Микросервисы Архитектура API дизайн

Введение: эта статья является третьей в серии «Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре», посвященной токену и аутентификации на уровне API. В этой статье анализируется большая часть используемого кода. Добро пожаловать, чтобы подписаться на эту серию статей.

1. Предыдущий обзор

Прежде чем приступить к объяснению этой статьи, давайте вспомним две предыдущие статьи. во-первыхПроектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре (1)Представлены предыстория проекта, техническое исследование и окончательный выбор. Статья 2Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре (2)Рисует краткую блок-схему входа и проверки и фокусируется на конкретной реализации проверки подлинности пользователя и выдачи токена.

check

Блок-схема проверки личности и разрешений API

В этой статье основное внимание уделяется аутентификации, включая два аспекта: легитимность токена и разрешения на операции на уровне API. Во-первых, легитимность токена легко понять. Во второй статье объясняется ряд процессов для получения токенов авторизации. Необходимо проверить, выдан ли токен сервером аутентификации. Во-вторых, для полномочий операции на уровне API запрос, для которого контекстная информация не имеет полномочий операции, отклоняется напрямую.Конечно, сначала проверяется действительность токена дизайна, а затем проверяется полномочия операции.Если предыдущая проверка напрямую отклонена, она пройдена Введите проверку разрешения на операцию.

2. Конечная точка аутентификации

Аутентификация в основном использует встроенную конечную точку/oauth/check_token, автор поставит анализ конечной точки впереди, потому что это единственная запись для аутентификации. Давайте посмотрим на основной код в интерфейсе API.

@RequestMapping(value = "/oauth/check_token")
   @ResponseBody
   public Map checkToken(CheckTokenEntity checkTokenEntity) {
    //CheckTokenEntity为自定义的dto
       Assert.notNull(checkTokenEntity, "invalid token entity!");
       //识别token
       OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(checkTokenEntity.getToken());
    //判断token是否为空
       if (token == null) {
           throw new InvalidTokenException("Token was not recognised");
       }
    //未过期
       if (token.isExpired()) {
           throw new InvalidTokenException("Token has expired");
       }
       //加载OAuth2Authentication
       OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());
    //获取response,token合法性验证完毕
       Map response = (Map) accessTokenConverter.convertAccessToken(token, authentication);
       //check for api permission
       if (response.containsKey("jti")) {
        //上下文操作权限校验
           Assert.isTrue(checkPermissions.checkPermission(checkTokenEntity));
       }
       
       response.put("active", true);    // Always true if token exists and not expired
       return response;
   }

Студенты, которые видели исходный код security-oauth, могут сразу увидеть, что приведенный выше код отличается от исходного кода, знакомого с/oauth/check_tokenПроцесс проверки тоже будет виден, тут автор правsecurity-oauthJAR был перекомпилирован, а часть исходного кода изменена для сценариев, необходимых для проекта. Основная причина заключается в добавлении проверки разрешений до уровня API.

3. Проверка действительности токена

сверхуCheckTokenEndpointИз вышеизложенного видно, что для проверки действительности токена первым шагом является идентификация токена в теле запроса. В качестве основного метода используетсяResourceServerTokenServicesкоторый предоставилreadAccessToken()метод. Класс реализации этого интерфейсаDefaultTokenServices, В предыдущей конфигурации я упомянул, что здесь настраивается TokenStore jdbc.

public class JdbcTokenStore implements TokenStore {
    ...
    public OAuth2AccessToken readAccessToken(String tokenValue) {
        OAuth2AccessToken accessToken = null;
        try {
            //使用selectAccessTokenSql语句,调用了私有的extractTokenKey()方法
            accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper() {
                public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
                    return deserializeAccessToken(rs.getBytes(2));
                }
            }, extractTokenKey(tokenValue));
        }
        //异常情况
        catch (EmptyResultDataAccessException e) {
            if (LOG.isInfoEnabled()) {
                LOG.info("Failed to find access token for token " + tokenValue);
            }
        }
        catch (IllegalArgumentException e) {
            LOG.warn("Failed to deserialize access token for " + tokenValue, e);
            //不合法则移除
            removeAccessToken(tokenValue);
        }
        return accessToken;
    }
    ...
    //提取TokenKey方法
    protected String extractTokenKey(String value) {
        if (value == null) {
            return null;
        }
        MessageDigest digest;
        try {
            //MD5
            digest = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }
        try {
            byte[] bytes = digest.digest(value.getBytes("UTF-8"));
            return String.format("%032x", new BigInteger(1, bytes));
        }
        catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
        }
    }
}

readAccessToken()Получите полную информацию о значении токена. Вышеприведенный код относительно прост, а логика несложна, здесь кратко поясняется. На следующем рисунке показана переменная информация проверки токена отладки. Читатели могут сделать это самостоятельно. Скриншоты приведены только для справки.

token

проверка токена отладки

Что касается следующих шагов,loadAuthentication()Загрузить учетные данные для определенного токена доступа. Получите учетные данные и токен какconvertAccessToken()параметр, чтобы получить ответ маркера проверки.

4. Проверка разрешений на уровне API

Проект автора в настоящее время основан на проверке разрешений через Интернет.Огромная единая прикладная система, оставшаяся прежде, постепенно разделяется, но полностью разделить и усовершенствовать ее в настоящее время невозможно. Чтобы быть совместимыми со старыми и новыми сервисами одновременно, минимизировать вторжение в бизнес-системы и добиться единства и независимости микросервисов. Согласно бизнес-сценарию, автор пытается проверить полномочия на операцию Auth. Первое, что приходит на ум, это то, что сервер ресурсов настраивает ResourceServer, например:

http.authorizeRequests()
.antMatchers("/order/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")

Для этого управление разрешениями API каждого рабочего интерфейса должно быть размещено в разных бизнес-службах. После того, как каждая служба получит запрос, она должна сначала получить информацию о разрешениях, такую ​​как роль и область действия, соответствующие токену, из службы аутентификации. . Этот метод определенно осуществим, но поскольку степень детализации аутентификации проекта более тонкая, и я пока не хочу вносить большие изменения в исходную систему, перед добавлением дизайна шлюза шлюз вызывает службу аутентификации для проверки. легитимности токена, поэтому я наконец решил вызвать систему Auth. , решить эти проверки вместе. Давайте рассмотрим сервер ресурсов, который мы настроили ранее:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .requestMatchers().antMatchers("/**")
                .and().authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and().logout()
                .logoutUrl("/logout")
                .clearAuthentication(true)
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
                .addLogoutHandler(customLogoutHandler());
    }
}

Из приведенного выше кода видно, что перехвата для всех ресурсов нет, потому что шлюз является соответствующей конечной точкой, которая вызывает систему аутентификации, и не все URL-адреса запросов будут проходить через систему аутентификации, поэтому для всех ресурсов. В системе проверки подлинности определите разрешения API, необходимые для интерфейса проверки подлинности, а затем сопоставьте их в соответствии с контекстом. Это второй метод, которым я сейчас пользуюсь. Конечно, недостатки этого метода также очевидны: при большом количестве параллелизма шлюз все равно будет тратить время на вызов системы Auth для аутентификации, и TPS неизбежно будет сильно падать, а некоторые сервисные интерфейсы, которые не требование аутентификации также будет недоступно. Еще один момент заключается в том, что для некоторых интерфейсов со специальными разрешениями требуется много контекстной информации, которая может быть не полностью охвачена, поэтому авторское решение разделено на два аспекта: один — попытаться классифицировать эти особые ситуации, а второй — попытаться классифицировать эти особые ситуации. определенный тип ситуации унифицированное решение; второе — уменьшить строгую проверку, напрямую отклонить отказ проверки контекста и передать для некоторых интерфейсов, прежде чем работать в интерфейсе, специальные места должны быть проверены снова.

Вышеупомянутая конечная точка упоминала, что исходный код был переписан здесь.CheckTokenEntityЭто настраиваемый DTO. Этот класс определяет контекст, необходимый для аутентификации. Здесь он относится к минимальному набору, который может проверять разрешения на операции, такие как URI, roleId,affiliateId и т. д. дополнительно определенныйCheckPermissionsинтерфейс, его методыcheckPermission(CheckTokenEntity checkTokenEntity)Результат проверки возвращается. И его конкретный класс реализации определяется в системе аутентификации. Пример, вызываемый в авторском проекте, выглядит следующим образом:

@Component
public class CustomCheckPermission implements CheckPermissions {
    @Autowired
    private PermissionService permissionService;
    @Override
    public boolean checkPermission(CheckTokenEntity checkTokenEntity) {
        String url = checkTokenEntity.getUri();
        Long affairId = checkTokenEntity.getAffairId();
        Long roleId = checkTokenEntity.getRoleId();
        //校验
        if (StringUtils.isEmpty(url) || affairId <= 0 || roleId <= 0) {
            return true;
        } else {
            return permissionService.checkPermission(url, affairId, roleId);
        }
    }
}

О упаковке баночкиspring-cloud-starter-oauth2Для конкретных изменений в содержании вы можете увидеть проект автора на GitHub в конце статьи. путем настройкиCustomCheckPermission, приоритетcheckPermission()метод, вы также можете проверить полномочия вашего собственного бизнеса, что очень гибко. Тут дело конкретное, автор только предоставляет интерфейс в проекте, а конкретную реализацию должен доделать читатель.

5. Резюме

Эта статья относительно проста и в основном объясняет токен и аутентификацию на уровне API. Аутентификация токенов на легитимность очень распространена.Аутентификация уровня API системой аутентификации разработана в соответствии с ее собственными бизнес-потребностями и статус-кво. Проверка этих двух штук предустановлена ​​в системе Auth, плюсы и минусы так же описаны в разделах выше. Наконец, дизайн архитектуры основан на собственных потребностях и статус-кво, а авторское решение предназначено только для справки.

Адрес источника этой статьи:
Гитхаб:GitHub.com/Доступный ETS2012/A…
Облако кода:git ee.com/can-ets/au-th-…


Ссылаться на

Техническая архитектура разрешений на уровне API для микросервисов

Связанное Чтение

Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре (1)
Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре (2)

keets wechatВы можете сканировать вышеуказанный общедоступный аккаунт WeChat, искать aoho и подписываться на мой блог!Придерживайтесь оригинального обмена технологиями, ваша поддержка побудит меня продолжать творить! наградаkeets WeChat Pay

WeChat награда

keets Alipay

Вознаграждение Alipay

  • Автор этой статьи: keets
  • Ссылка на эту статью: га cloud.club/2017/10/24/…
  • Уведомление об авторских правах:Все статьи в этом блоге, если не указано иное, используютCC BY-NC-SA 3.0соглашение. Пожалуйста, укажите источник!