Рубрики
Без рубрики

Безопасность Spring с использованием OAuth2 с AngularJS [JWT]

Блог первоначально опубликован в моем блоге js blogs.github.технологии ввода-вывода, используемые последовательно… Помеченный как угловой, учебник, безопасность, java.

Блог первоначально опубликован в моем блоге js blogs.github.io

  • Вступление
  • Используемые технологии
  • Схема последовательности потока OAuth2
  • Магазин Jwttoken

Вступление

В этом сообщении в блоге будет продемонстрирована интеграция spring-security и angular JS с использованием токена JWT. В моем предыдущем блоге объясняется, как мы можем настроить классы для интеграции spring security с angular. Я рекомендую вам посмотреть мой предыдущий видеоурок, потому что этот урок является дополнением к этому видео.

Весенняя безопасность с использованием OAuth2 с Angular JS

Джитендра Сингх Бишт ・ 27 июня ・ 1 минута читать

В этом видеоуроке я создал TokenStore класс для хранения токена, который я перепишу в этом блоге для генерации токенов JWT.

Используемые технологии

  • Ява
  • Пружинный ботинок
  • Пружинная защита
  • Угловой JS 8

Схема последовательности потока OAuth2

Магазин Jwttoken

В этом видеоуроке я создал хранилище токенов на основе хэш-карты. Теперь мы собираемся перезаписать этот класс и создадим одну реализацию на основе JWT.

package com.demo.security.config;

import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.stereotype.Component;

import java.security.interfaces.ECPrivateKey;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class JwtTokenStore implements ITokenStore {
    // 1
    private final String tokenSignKey = "c5d4d70419bd4909a1e502812c6e1f2b";

    // 2
    private final String REG_ID = "clientRegistrationId";
    private final String NAMED_KEY = "namedAttributeKey";
    private final String AUTHORITIES = "authorities";
    private final String ATTRIBUTES = "attributes";

    // 3
    public String generateToken( Authentication authentication ) throws Exception {

        OAuth2AuthenticationToken token = ( OAuth2AuthenticationToken ) authentication;
        DefaultOAuth2User userDetails = ( DefaultOAuth2User ) token.getPrincipal();

        // 4
        List auths = userDetails.getAuthorities()
                .stream()
                .map( GrantedAuthority::getAuthority )
                .collect( Collectors.toList());
        // 5
        JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                .subject(  userDetails.getAttribute("id").toString())
                .expirationTime( getDate( 5, ChronoUnit.HOURS ) )
                .claim( NAMED_KEY, "name" )
                .claim( ATTRIBUTES, userDetails.getAttributes() )
                .claim( AUTHORITIES, auths )
                .claim( REG_ID, token.getAuthorizedClientRegistrationId() )
                .build();

        // 6
        ECKey key = new ECKeyGenerator( Curve.P_256 ).keyID( tokenSignKey ).generate();
        JWSHeader h = new JWSHeader.Builder( JWSAlgorithm.ES256 )
                .type( JOSEObjectType.JWT )
                .keyID( key.getKeyID() )
                .build();
        SignedJWT jwt = new SignedJWT( h, claimsSet );
        // 7
        jwt.sign( new ECDSASigner( ( ECPrivateKey ) key.toPrivateKey() ) );
        return jwt.serialize();
    }

    // 8
    public Authentication getAuth( String jwt ) throws Exception {
        SignedJWT signedJWT = SignedJWT.parse( jwt );
        // 9
        validateJwt( signedJWT );

        JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();

        // 10
        String clientRegistrationId = (String ) claimsSet.getClaim( REG_ID );
        String namedAttributeKey = (String) claimsSet.getClaim( NAMED_KEY );
        Map attributes = (Map)claimsSet.getClaim( ATTRIBUTES );
        Collection authorities =( (List ) claimsSet.getClaim( AUTHORITIES ))
                .stream().map( SimpleGrantedAuthority::new ).collect( Collectors.toSet());

        // 11
        return new OAuth2AuthenticationToken(
                new DefaultOAuth2User( authorities, attributes, namedAttributeKey ),
                authorities,
                clientRegistrationId
        );
    }

    private static Date getDate( long amount, TemporalUnit unit ) {
        return Date.from(
                LocalDateTime.now()
                .plus( amount, unit )
                .atZone( ZoneId.systemDefault() )
                .toInstant()
        );
    }

    private void validateJwt( JWT jwt ) throws Exception {
        // 12
        if(jwt.getJWTClaimsSet().getExpirationTime().before( new Date() )){
            throw new RuntimeException("Token Expired!!");
        }

        // Add validation logic here..
    }
}

В приведенную выше кодовую базу я добавил номера комментариев, которые я собираюсь объяснить здесь.

  1. Ключ подписи токена будет использоваться для подписи JWT. Вы можете использовать свой собственный ключ.
  2. Атрибуты, которые я собираюсь получить от объекта аутентификации и поместить их в JWT, который я буду использовать позже для создания объекта аутентификации.
  3. Метод generateToken примет объект аутентификации и создаст из него токен JWT.
  4. Собирая все имена авторитетов.
  5. Подготовка утверждений JWT с такими значениями, как Тема, Полномочия, атрибуты, Именованный ключ атрибута (требуется для DefaultOAuth2User) и время истечения срока действия токена
  6. Подготовьте ключ подписи для подписи токена JWT.
  7. Подпишите жетон и возвращайтесь.
  8. Метод getAuth принимает токен JWT и подготавливает объект аутентификации из действительного токена.
  9. Проверка токена JWT в настоящее время я проверяю только время истечения срока действия, но вы можете добавить свою собственную логику проверки.
  10. Получите необходимые объекты из утверждений JWT, которые будут использоваться для подготовки токена аутентификации.
  11. Подготовьте и верните действительный Токен аутентификации OAuth2 .
  12. Сверка времени истечения срока действия с текущим временем.

Работающий код можно найти здесь .

Оригинал: “https://dev.to/jeetmp3/spring-security-using-oauth2-with-angularjs-jwt-4nmd”