<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    paulwong

    SPRING BOOT OAUTH2 + KEYCLOAK - service to service call

    employee-service調(diào)用department-service,如果要按OAUTH2.0流程,只需要提供client-id和client-secrect即可。在KEYCLOAK中引入service-account,即配置該employee-service時(shí),取消standard-flow,同時(shí)激活service-account。
    employee-service的application.yaml文件,其中的public-key要從KEYCLOAK中取
    server:
       port: 8090
    # Can be set to false to disable security during local development
    rest:
       security:
          enabled: true
          #issuer-uri: http://localhost:8080/auth/realms/dev
          api-matcher: /api/**
          cors:
             allowed-origins: '*'
             allowed-headers: '*'
             allowed-methods: GET,POST,PUT,PATCH,DELETE,OPTIONS
             max-age: 3600

    security:
       oauth2:
          resource:
             filter-order: 3
             id: test-employee-service
             token-info-uri: ${rest.security.issuer-uri}/protocol/openid-connect/token/introspect
             user-info-uri: ${rest.security.issuer-uri}/protocol/openid-connect/userinfo
             jwt:
                key-value: | 
                   -----BEGIN PUBLIC KEY-----
                   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB
                   -----END PUBLIC KEY-----

    # To access another secured micro-service
          client:
             client-id: test-employee-service
             #client-secret: 25c33006-e1b9-4fc2-a6b9-c43dbc41ecd0
             user-authorization-uri: ${rest.security.issuer-uri}/protocol/openid-connect/auth
             access-token-uri: ${rest.security.issuer-uri}/protocol/openid-connect/token
             scope: openid
             grant-type: client_credentials
             is-client-only: true

    #Logging Configuration
    logging:
       level:
          org.springframework.boot.autoconfigure.logging: INFO
          org.springframework.security: DEBUG
          org.arun: DEBUG
          root: INFO

    application-dev.yaml
    rest:
       security:
          issuer-uri: http://10.80.27.69:8180/auth/realms/quickstart

    department-service:
       url: http://10.80.27.69:8095/api/departments/1

    security:
       oauth2:
          client:
             client-secret: db25cdbd-605b-429d-bd92-96705bdf1474

    department-service的application.yaml
    server:
       port: 8095
    # Can be set to false to disable security during local development
    rest:
       security:
          enabled: true
          #issuer-uri: http://localhost:8080/auth/realms/dev
          api-matcher: /api/**
          cors:
             allowed-origins: '*'
             allowed-headers: '*'
             allowed-methods: GET,POST,PUT,PATCH,DELETE,OPTIONS
             max-age: 3600

    security:
       oauth2:
          resource:
             filter-order: 3
             id: test-department-service
             token-info-uri: ${rest.security.issuer-uri}/protocol/openid-connect/token/introspect
             user-info-uri: ${rest.security.issuer-uri}/protocol/openid-connect/userinfo
             jwt:
                key-value: | 
                   -----BEGIN PUBLIC KEY-----
                   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB
                   -----END PUBLIC KEY-----

    #Logging Configuration
    logging:
       level:
          org.springframework.boot.autoconfigure.logging: INFO
          org.springframework.security: DEBUG
          org.arun: DEBUG
          root: INFO

    application-dev.yaml
    rest:
       security:
          issuer-uri: http://10.80.27.69:8180/auth/realms/quickstart

    employee-service的pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi
    ="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation
    ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.18.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>org.arun.springoauth</groupId>
        <artifactId>spring-oauth2-employee-service</artifactId>
        <version>1.0.0</version>
        <name>spring-oauth2-employee-service</name>
        <description>Employee Service</description>

        <properties>
            <java.version>1.8</java.version>
            <spring-boot.version>2.1.18.RELEASE</spring-boot.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <!-- <version>2.1.18.RELEASE</version> -->
                <version>${spring-boot.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <layout>ZIP</layout>
                        <excludes>
                            <exclude>
                                <groupId>*</groupId>
                                <artifactId>*</artifactId>
                            </exclude>
                        </excludes>
                        <includes>
                            <include>
                                <groupId>com.paul</groupId>
                            </include>
                        </includes>
                    </configuration>
                </plugin>
            </plugins>
        </build>

    </project>

    將jwt格式的access_token轉(zhuǎn)成Authentication的類JwtAccessTokenCustomizer
    package org.arun.springoauth.employee.config;

    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.security.oauth2.resource.JwtAccessTokenConverterConfigurer;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.AuthorityUtils;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.security.oauth2.provider.OAuth2Request;
    import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
    import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

    @Configuration
    public class JwtAccessTokenCustomizer extends DefaultAccessTokenConverter implements JwtAccessTokenConverterConfigurer {

        private static final Logger LOG = LoggerFactory.getLogger(JwtAccessTokenCustomizer.class);

        private static final String CLIENT_NAME_ELEMENT_IN_JWT = "resource_access";

        private static final String ROLE_ELEMENT_IN_JWT = "roles";

        private ObjectMapper mapper;

        @Autowired
        public JwtAccessTokenCustomizer(ObjectMapper mapper) {
            this.mapper = mapper;
            LOG.info("Initialized {}", JwtAccessTokenCustomizer.class.getSimpleName());
        }

        @Override
        public void configure(JwtAccessTokenConverter converter) {
            converter.setAccessTokenConverter(this);
            LOG.info("Configured {}", JwtAccessTokenConverter.class.getSimpleName());
        }

        /**
         * Spring oauth2 expects roles under authorities element in tokenMap, but
         * keycloak provides it under resource_access. Hence extractAuthentication
         * method is overriden to extract roles from resource_access.
         *
         * 
    @return OAuth2Authentication with authorities for given application
         
    */
        @Override
        public OAuth2Authentication extractAuthentication(Map<String, ?> tokenMap) {
            LOG.debug("Begin extractAuthentication: tokenMap = {}", tokenMap);
            JsonNode token = mapper.convertValue(tokenMap, JsonNode.class);
            Set<String> audienceList = extractClients(token); // extracting client names
            List<GrantedAuthority> authorities = extractRoles(token); // extracting client roles

            OAuth2Authentication authentication = super.extractAuthentication(tokenMap);
            OAuth2Request oAuth2Request = authentication.getOAuth2Request();

            OAuth2Request request = new OAuth2Request(oAuth2Request.getRequestParameters(), oAuth2Request.getClientId(),
                    authorities, true, oAuth2Request.getScope(), audienceList, nullnullnull);

            Authentication usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(
                    authentication.getPrincipal(), "N/A", authorities);
            LOG.debug("End extractAuthentication");
            return new OAuth2Authentication(request, usernamePasswordAuthentication);
        }

        private List<GrantedAuthority> extractRoles(JsonNode jwt) {
            LOG.debug("Begin extractRoles: jwt = {}", jwt);
            Set<String> rolesWithPrefix = new HashSet<>();

            jwt.path(CLIENT_NAME_ELEMENT_IN_JWT).elements().forEachRemaining(e -> e.path(ROLE_ELEMENT_IN_JWT).elements()
                    .forEachRemaining(r -> rolesWithPrefix.add("ROLE_" + r.asText())));

            final List<GrantedAuthority> authorityList = AuthorityUtils
                    .createAuthorityList(rolesWithPrefix.toArray(new String[0]));
            LOG.debug("End extractRoles: roles = {}", authorityList);
            return authorityList;
        }

        private Set<String> extractClients(JsonNode jwt) {
            LOG.debug("Begin extractClients: jwt = {}", jwt);
            if (jwt.has(CLIENT_NAME_ELEMENT_IN_JWT)) {
                JsonNode resourceAccessJsonNode = jwt.path(CLIENT_NAME_ELEMENT_IN_JWT);
                final Set<String> clientNames = new HashSet<>();
                resourceAccessJsonNode.fieldNames().forEachRemaining(clientNames::add);

                LOG.debug("End extractClients: clients = {}", clientNames);
                return clientNames;

            } else {
                throw new IllegalArgumentException(
                        "Expected element " + CLIENT_NAME_ELEMENT_IN_JWT + " not found in token");
            }

        }

    }



    Reference
    https://medium.com/@bcarunmail/securing-rest-api-using-keycloak-and-spring-oauth2-6ddf3a1efcc2



    posted on 2021-10-26 17:06 paulwong 閱讀(571) 評(píng)論(0)  編輯  收藏 所屬分類: OAUTH2

    主站蜘蛛池模板: 亚洲天堂在线播放| 亚洲欧洲在线观看| 国产亚洲Av综合人人澡精品| 亚洲成年人免费网站| 亚洲无砖砖区免费| 无码中文字幕av免费放| 亚洲色最新高清av网站| 暖暖免费高清日本一区二区三区| 欧洲 亚洲 国产图片综合| 免费视频淫片aa毛片| 色综合久久精品亚洲国产| 免费大黄网站在线观| ssswww日本免费网站片| 久久精品国产96精品亚洲| 亚州免费一级毛片| 亚洲色大成网站www永久网站| 国产成人免费永久播放视频平台| 美女免费视频一区二区| 国产亚洲精品成人AA片新蒲金| 两个人看的www免费视频中文| 久久亚洲精品无码AV红樱桃| 男女免费观看在线爽爽爽视频| 一本天堂ⅴ无码亚洲道久久| 免费大黄网站在线看| 久久免费视频观看| 亚洲综合av一区二区三区| 亚洲国产成人精品91久久久| 免费在线观影网站| 亚洲深深色噜噜狠狠网站| 亚洲国产aⅴ综合网| 十八禁无码免费网站| 亚洲中文字幕无码中文字| 亚洲国产精品无码久久青草 | 亚洲AV无码一区二区三区网址 | 亚洲国产精品专区| 国产精品无码一区二区三区免费 | 亚洲永久网址在线观看| 亚洲中文字幕视频国产| 亚洲免费视频网址| 免费人成视频在线播放| 久久亚洲精品无码AV红樱桃|