Содержание
Доброго дня, уважаемые коллеги! Мучаюсь несколько дней, не смог решить проблему, поэтому взываю о помощи Пикабу 🙂
Итак –
Есть флешка (токен) сбербанка бизнес онлайн, есть комп с Windows 10 Pro.
На токене, чтобы запустить страницу входа банк, нужно запустить приложение start.exe.
Браузером по умолчанию в системе был назначен Chrome (мозиллу тоже пробовал).
Так вот, при запуске приложения start.exe, система открывает страницу входа через….internet explorer 11, абсолютно игнорируя примененные настройки браузера по умолчанию.
Почему нужен chrome – при обмене с банком в обе стороны создается файл kl_to_1c.txt
При дублировании этого файла в одной папке explorer создает такой же, только с постфиксом (1), и соответственно ни банк, ни 1С в автоматическом режиме его не видят.
В хроме эта проблема решалась установкой расширения из магазина приложений, которое заставляло его перезаписывать, а не создавать похожий.
в Win7 таких проблем не было – все открывалось через установленный по умолчанию браузер.
что с 10-кой не так – не пойму)
Памажыте пожалуйста)
–>
применимо к: Windows server 2022, Windows server 2019, Windows Server 2016 и Windows 10
Протокол привязки токенов позволяет приложениям и службам криптографически привязывать свои маркеры безопасности к уровню TLS для устранения атак с кражой и воспроизведением маркеров. Долгосрочные, однозначно идентифицируемые привязки TLS [RFC5246] могут охватывать несколько сеансов TLS и соединений.
Поддерживаемые версии:
- Windows 10, версия 1507 – Отключено по умолчанию
- Добавлен протокол привязки маркеров [черновик-IETF-токбинд-Protocol-01]
- WinInet & HTTP.SYS поддержку привязки маркеров по протоколу HTTP &
- Windows 10, версии 1511 и 1607 и Windows Server 2016 по – умолчанию
- Протокол привязки токена обновлен [черновик-IETF-токбинд-Protocol-01]
- Расширение TLS для согласования привязки токена Добавлено [черновик-Попов-токбинд-переговоры-00]
- WinInet & HTTP.SYS поддержка привязки маркера по протоколу HTTP обновлена &
- Windows 10, версия 1507 с обслуживанием update KB4034668, Windows 10, версия 1511 с обслуживанием update KB4034660, Windows 10, версия 1607 и Windows Server 2016 с обслуживанием обновления KB4034658 протокол привязки маркеров, версия 0,10 включена по умолчанию
- Протокол привязки токена обновлен [черновик — IETF-токбинд-Protocol-10]
- Добавлено расширение TLS для согласования привязки маркеров [черновик-IETF-токбинд-переговоры-05]
- WinInet & HTTP.SYS поддержка привязки маркера по протоколу HTTP обновлена &
- Windows 10, версия 1703 поддерживает протокол привязки маркеров версии 0,10 – Включено по умолчанию
- Протокол привязки токена обновлен [черновик — IETF-токбинд-Protocol-10]
- Добавлено расширение TLS для согласования привязки маркеров [черновик-IETF-токбинд-переговоры-05]
- WinInet & HTTP.SYS поддержка привязки маркера по протоколу HTTP обновлена &
- Windows устройства с включенной безопасностью на основе виртуализации будут поддерживать ключи привязки маркеров в защищенной среде, изолированной от работающей операционной системы.
сведения о поддержке ASP .net можно найти в источнике ссылки на платформа .NET Framework.
дополнительные сведения о платформа .NET Framework см. в следующих разделах:
-
Улучшения работы с сетью
-
Класс .NET Токенбиндинг
–>
Токен — это устройство в виде USB-флешки с защищенной паролем картой памяти, на которой хранится информация для создания подписи. Токен обеспечивает двухфазную аутентификацию пользователя: для работы необходимо вставить токен в USB-разъем компьютера и ввести пароль.
В России два вида токенов:
- Рутокен – ключевой носитель, разработанный и широко применяемый в России. Продукты на базе Рутокена широко используются в коммерческих и государственных проектах. Кроме того, безопасность рутокенов постоянно повышается — в частности, в новых версиях операции шифрования документа выполняются не только на компьютере, но и в самом устройстве. Это делает электронную подпись более защищенной от вирусов и хакерских атак.
- Е-токен – европейский вариант ключевого носителя. Е-токены могут содержать практически любой дополнительный чип RFID (радио-метку) для интеграции с системами контроля и управления доступом в помещения.
Только СКБ Контур выпускает электронные подписи со встроенной лицензией. Это позволяет подписывать файлы с любого рабочего места — лицензия СКЗИ уже есть на токене. Команды СКБ Контур и Рутокена взаимодействовали на этапе разработки, благодаря чему пользователи наших услуг получают качественный и удобный носитель, который легко устанавливать и использовать.
УЦ СКБ Контур выпускает все виды электронных подписей.
В Spring Security JWT-токен используется в OAuth 2 как access token. Он выдается клиенту сервером авторизации, клиент отправляет его при обращении к серверу ресурсов. (А сервер ресурсов проверяет его, обращаясь к серверу авторизации).
Но этот пример — самописная реализация stateless REST API на JWT, единое приложение, которое и выдает, и проверяет токен. И выдает REST API.
На этом примере можно увидеть, как написать свой фильтр авторизации, как сформировать и проверить JWT-токен. Но в реальном проекте этот пример лучше не использовать.
Если нужен JWT без OAuth2, то есть в Spring Boot есть и такое готовое решение.
Задача
В этой статье будет чистый REST-сервис без фронтенда. Подразумевается, что фронтенд написан отдельно: например, на каком-нибудь JavaScript-фрейворке.
Для отправки запросов мы будем использовать программу POSTMAN. Например, для «входа» с именем/паролем и получения JWT-токена. А также для запроса защищенных страниц.
В этом примере наш старый REST-контроллер останется, а настройка Spring Security не особо поменяется — скорее, она дополнится.
- Мы добавим в приложение конечную точку /authenticate для аутентификации. Сюда приходят имя и пароль от пользователя. Приложение проверяет пароль, и если он верный, высылает пользователю в ответ JWT-токен.
- Во всех дальнейших запросах пользователь обязан высылать в заголовке JWT-токен, наше приложение проверяет подлинность токена в специально написанном фильтре JWTFilter и, если он корректен, пропускает запрос дальше.
Подготовка
REST-контроллер
Итак, наш основной REST-контроллер остается прежним:
@RestController public class HelloController { @GetMapping("/") public String hello() { return "Hello"; } // сюда доступ разрешен только user и admin @GetMapping("/user") public String user() { return "User"; } // сюда доступ разрешен только admin @GetMapping("/admin") public String admin() { return "Admin"; } }
Он нужен для того, чтобы запретить к нему доступ и потом разрешить только авторизованным пользователям.
Аутентификация с пользовательским UserDetailsService
Настройка аутентификации такая:
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } //... @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } }
Подробнее об аутентификации с UserDetailsService есть статья.
Если кратко, мы переопределяем метод loadUserByUsername(), чтобы Spring Security понимал, как взять пользователя по его имени из хранилища. Имея этот метод, SS может сравнить переданный пароль с настоящим и аутентифицировать пользователя (либо не аутентифицировать).
CustomUserDetailsService:
@Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private MyUserRepository dao; @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { MyUser myUser= dao.findByLogin(userName); if (myUser == null) { throw new UsernameNotFoundException("Unknown user: "+userName); } UserDetails user = User.builder() .username(myUser.getLogin()) .password(myUser.getPassword()) .roles(myUser.getRole()) .build(); return user; } }
Пользователи хранятся в In-Memory базе данных H2. Работаем через Hibernate.
Модель пользователя:
@Entity public class MyUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) long id; private String login; private String password; private String position; private String role; // геттеры/сеттеры }
И репозиторий:
@Repository public interface MyUserRepository extends JpaRepository { MyUser findByLogin(String login); }
А данными заполняем базу на старте приложения с помощью data.sql (этот файл надо положить в папку /resources, а в application.yml включить его запуск):
insert into my_user(login, position, password, role) values('user', '1', 'password', 'USER'); insert into my_user( login, position, password, role) values('admin', '2', 'password', 'ADMIN');
А теперь перейдем собственно в JWT-токену.
Библиотека для работы с JWT-токеном
Для работы с JWT добавим Maven-зависимость:
io.jsonwebtoken jjwt 0.9.1
Для работы с JWT-токеном уже написаны утилиты, так что используем готовую. В ней есть метод формирования токена, методы извлечения имени пользователя и других данных. Метод формирования токена изменим так, чтобы записывать в токен еще список authorities в виде клейма authorities.
Во всех методах извлечения данных JWT-токен заодно проверяется на предмет не истек ли он, и валидна ли подпись.
Эти методы утилиты нам пригодятся:
@Service public class JWTUtil { @Value("${jwt.secret}") private String SECRET_KEY; @Value("${jwt.sessionTime}") private long sessionTime; // генерация токена (кладем в него имя пользователя и authorities) public String generateToken(UserDetails userDetails) { Map claims = new HashMap<>(); String commaSeparatedListOfAuthorities= userDetails.getAuthorities().stream().map(a->a.getAuthority()).collect(Collectors.joining(",")); claims.put("authorities", commaSeparatedListOfAuthorities); return createToken(claims, userDetails.getUsername()); } //извлечение имени пользователя из токена (внутри валидация токена) public String extractUsername(String token) { return extractClaim(token, Claims::getSubject); } //извлечение authorities (внутри валидация токена) public String extractAuthorities(String token) { return extractClaim(token, claims -> (String)claims.get("authorities")); } // другие методы }
Это была подготовка. Перейдем, наконец, к написанию своего кода, касающегося JWT.
Конечная точка аутентификации для выдачи JWT-токена
Тут собственно выдается JWT-токен. Пользователь делает POST-запрос с именем и паролем по адресу /authenticate, а в ответ получает сгенерированынй токен. Токен генерится методом generateToken() из утилиты выше.
@RestController public class AuthenticationController { @Autowired private AuthenticationManager authenticationManager; @Autowired private JWTUtil jwtTokenUtil; @PostMapping("/authenticate") @ResponseStatus(HttpStatus.OK) public AuthResponse createAuthenticationToken(@RequestBody AuthRequest authRequest) { Authentication authentication; try { authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authRequest.getName(), authRequest.getPassword())); System.out.println(authentication); } catch (BadCredentialsException e) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Имя или пароль неправильны", e); } // при создании токена в него кладется username как Subject claim и список authorities как кастомный claim String jwt = jwtTokenUtil.generateToken((UserDetails) authentication.getPrincipal()); return new AuthResponse(jwt); } }
Запрос имеет такой формат:
public class AuthRequest { private String name; private String password; // геттеры сеттеры }
А ответ такой:
public class AuthResponse { private String jwtToken; // геттер и сеттер }
Если имя и пароль верные, токен возвращается в AuthResponse, а если нет — выбрасывается исключение и на фронтенд приходит сообщение об ошибке.
Фронтенд сохраняет у себя JWT-токен, и потом использует его при каждом запросе.
Немного о «разлогине»
Если пользователь хочет выйти, токен должен быть уничтожен на фронтенде. На бэкенде (в нашем Spring приложении) он продолжит действовать до истечения своего срока. А вообще теоретически можно сделать черный список токенов, но не в этом примере.
Еще: чтобы сделать токены сразу всех пользователей недействительными, достаточно поменять секретный код. Но тогда разлогинены будут все сразу.
В этом проблема JWT-токена — нужны обходные пути для того, чтобы сделать его недействительным.
Перейдем ко второй принципиальной части — фильтру, проверяющему токен при каждом запросе.
Фильтр, проверяющий JWT-токен при каждом запросе
Итак, JWT-токен выдан, клиент его нам отправляет при каждом запросе, надо этот токен при каждом запросе проверять (и извлекать из него имя пользователя). Для этого напишем фильтр JWTFilter. Он расширяет OncePerRequestFilter и происходит в нем следующее:
- При каждом запросе из заголовка Authorization берем JWT-токен (он начинается с префикса «Bearer«).
- Извлекаем из него имя пользователя (claim subject) и список authorities (claim authorities). Оба клейма мы записывали в токен при его генерации в контроллере.
- Одновременно при извлечении claims проверяется валидность токена. Для этого не надо делать никаких запросов в базу: достаточно самого токена и jwt.secret (прописанного в application.yml). На основе этого секрета токен генерился, и на основе него он потом каждый раз проверяется с помощью хеш-функции (это делает библиотека jjwt).
- Если все ок, то имея имя пользователя и список authorities (извлеченные в п.2), создаем объект Authentication (точнее, его подкласс UsernamePasswordAuthenticationToken). И устанавливаем объект Authentication в SecurityContext. Так нужно для Spring Security.
- Если с токеном не все ок, то в п. 2-3 выбросился исключение, и фильтр не пропустит запрос в контроллер к защищенному /url.
@Component public class JWTFilter extends OncePerRequestFilter { @Autowired private JWTUtil jwtUtil; @Autowired CustomUserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); //если подпись не совпадает с вычисленной, то SignatureException //если подпись некорректная (не парсится), то MalformedJwtException //если время подписи истекло, то ExpiredJwtException username = jwtUtil.extractUsername(jwt); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { String commaSeparatedListOfAuthorities = jwtUtil.extractAuthorities(jwt); List authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(commaSeparatedListOfAuthorities); UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( username, null, authorities); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } chain.doFilter(request, response); } }
Настройка авторизации: собираем все вместе
Тут все как раньше, но только:
- отключаем csrf,
- отключаем сессии
- и добавляем наш фильтр JWTFilter перед фильтром UsernamePasswordAuthenticationFilter.
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JWTFilter jwtFilter; // еще поля и методы // Бин AuthenticationManager используется в контроллере аутентификации (см. выше) @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } // тут отключаем сессии и добавляем фильтр JWTFilter @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/authenticate").permitAll() .and().authorizeRequests().antMatchers("/user/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN") .and().authorizeRequests().antMatchers("/admin/**").hasAuthority("ROLE_ADMIN") .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); } }
Проверка
Запустим приложении и убедимся, что все работает.
Получение JWT-токена
Отправим POST-запрос нужного формата по адресу /authencate:
Отправка запроса с JWT-токеном
Токен получен, теперь с ним можно попасть на защищенную страницу. Для этого добавим его к запросу /user в заголовок Authorization.
При этом выберем тип Bearer-токен — это значит, что префикс Bearer будет добавлен к токену.
Как видно, страница /user получена.
Вид JWT-токена
Если декодировать токен на сайте https://jwt.io/, то в нем видны наши добавленные клеймы sub (имя пользователя) и authorities:
Остальные два клейма:
- exp — когда истекает токен
- iat -когда выпущен токен
Исходный код
Он находится на GitHub.
Пользователи социальных сетей привыкли использовать логин и пароль в качестве данных для авторизации в сервисах. Другие идут дальше и предпочитают использовать QR-код для входа. Однако оба этих метода слишком муторны и неудобны, когда необходимо подключить к аккаунту бота или авторизоваться в сервисе через стороннее приложение. В таком случае в Дискорд на помощь приходят токены. Расскажем, как использовать токен в Дискорде и что делать, если он устарел.
Итак, если вас заинтересовала тема работы с токенами, то, скорее всего, вам:
- Необходимо авторизоваться через сторонний сервис в Дискорде, а стандартные логин и пароль не принимаются.
- Необходимо разработать бота для сервера в Дискорде. Скорее всего, это ваш первый бот, так как тема использования token изучается в самом начале.
- Нужно разработать собственное приложение, в котором происходит авторизация через Дискорд.
В ином случае вам просто интересно значение этого термина, так как оно часто мелькает в материалах про компьютеры. В любом случае, у самого термина есть только одно определение.
Токен – это своеобразный идентификационный ключ, позволяющий авторизоваться или подключиться к какому-то аккаунту. В отличие от логинов и паролей, токен – это одна большая генерируемая строка, а не две пользовательские.
Еще одна отличительная особенность token-ов в том, что их срок действия и права доступа легко настраивать, да и они одноразовые (не всегда). Например, планируется выдать доступ только к имени аккаунта и только на 24 часа, выставляете эти настройки в параметрах, и вуаля: token с пользовательскими настройками готов.
Впрочем, описание выше относится к самому термину «токен». В Дискорде термин «token» означает своеобразный ключ аутентификации, который позволяет обращаться к созданному боту (при его разработке) либо проходить авторизацию в сторонних сервисах. Существуют даже token grabber-ы, которые позволяют считать данные с аккаунта.
И еще, даже если данные попадут в какую-то пиратскую базу, то их можно отозвать или сбросить. В общем, преимущество токенов в их компактности и безопасности.
Итак, чтобы получить token для бота, необходимо сначала создать этого бота. Для этого вам понадобится владеть навыками программирования. Впрочем, опустим пункт с разработкой. Вот, у вас есть готовый бот, который осталось подключить к Дискорду с помощью token-а. Для этого выполняем следующие действия:
- Откройте сайт Дискорда для разработчиков. Он находится по этой ссылке https://discord.com/developers/applications
- Нажмите кнопку «New Application».
- Выберите название нового приложения.
- Заполните нужные данные для бота. Там нужно указать его описание, а также статус. Однако, все это опционально.
- Перейдите в раздел «Bot».
- Найдите заголовок поля «Token». Под ним будет ссылка «Click to Reveal token». Нажмите на нее.
- Вместо ссылки отобразится длинный текст, состоящий из символов и цифр.
Поздравляем, вы нашли токен для вашего бота. Теперь осталось указать этот токен в коде. К слову, чтобы добавить бота на сервер, токен не поможет, нужно получать специальную ссылку, которая находится в том же разделе. Кстати, здесь же можно сбросить старый токен и сгенерировать новый. Для этого нажмите на синюю кнопку «Regenerate». Учтите, что после этого старый токен потеряет актуальность, а потому боты на серверах перестанут работать.
Способ выше отлично подходил, если необходимо было получить токен для подключения к одному боту. А что делать, если вместо бота нужно подключиться к собственной учетной записи? В таком случае придется воспользоваться другим методом. Алгоритм действий:
- Откройте главную страницу Дискорда в браузере. Через устанавливаемую версию ничего сделать не получится.
- Нажмите кнопку «F12» (или «Ctrl» + «Shift» + «I»). Должны открыться инструменты разработчика.
- Перейдите в раздел «Сеть» («Network»).
- Введите в окно поиска фразу «/api/v9».
- Откройте любой найденный файл.
- Перейдите в раздел «Заголовки» («Headers»). По умолчанию там выбран «Предварительный просмотр», если вы сидите с Google chrome.
- Прокрутите его до строки «Authorization». После нее будет указан ваш токен.
- Скопируйте его.
Готово. Теперь вы можете указать его в нужном поле для авторизации. Учтите, что токен равносилен данным авторизации, а потому его не стоит оставлять на виду у всех.
Итак, зайти напрямую через токен не получится. Он не отправляется GET-запросом, а значит, просто скопировать текст в строку URL нельзя. Однако не стоит разочаровываться и возмущаться, зачем эти инструкции выше. Token часто используется сторонними сервисами для авторизации.
При необходимости вы можете скопировать идентификационный текст именно туда. Но учтите, токен привязан к одной сессии в Дискорде. То есть, если пользователь нажмет кнопку «Выйти», token автоматически станет недействительным.
На просторах интернета довольно часто предлагают приобрести токен за небольшую круглую сумму. С одной стороны, почему бы не взять, ведь это выгодно, цена-то практически мизерная. Но не ведитесь на это, так как большинство таких предложений исходят от мошенников. Оставшаяся доля продавцов может продать токен, но только не ваш, а чей-то. Да и он перестанет быть действительным, когда владелец сбросит настройки или завершит сессию.
Запомните, все token-ы ваших ботов и аккаунтов получаются бесплатным путем и без посредников. Не стоит верить этим банальным схемам мошенников.
Вы строго следовали инструкциям выше и, кажется, все получилось, авторизация через Дискорд прошла успешно, бот подключен и все вроде бы идеально. Однако через время вдруг эта инструкция уже не работает, а вместо желанного результата появляется ошибка «Токен устарел». Что же делать в таком случае?
Как мы уже говорили выше, эти секретные token-ы легко отозвать. Чтобы сделать это с ботом, достаточно зайти в панель управления приложением, в раздел «Bot» и нажать «Regenerate», а после скопировать новые данные. Готово, осталось закинуть новые данные в код с ботом и радоваться результату.
Чтобы сбросить token для аккаунта, достаточно выйти из профиля на сайте, где производилось копирование token. После авторизуйтесь снова, повторите алгоритм из раздела «Как узнать Дискорд-токен для аутентификации». Новые данные запишите в надежное место, а после скопируйте в настройки сервиса, где появилась ошибка. Как вы уже поняли, устаревший token – это некритичная ошибка, а лишь мера безопасности, спасающая от тех самых мошенников, которые продают аккаунты.
Надеемся, что эти способы помогли вам. Если остались вопросы, то смело задавайте их в комментариях. Благодарим за прочтение.
24.11.2021 20:44 2 Евгений Верещака Информационный портал IT Техник
ли со статьей или есть что добавить?