paulwong

#

EVEN DRIVEN - SPRING CLOUD STREAM 3.x - Functional Programming Model

SPRING CLOUD STREAM 3.x 版本时,之前的一些编程模式,如@Enablebindding,@StreamListenner等注释被废弃了,这是由于一些框架的代码必需由用户编写,如配置框架用的Input MessageChannel,Output  MessageChannel,连接MessageHandler与MessageChannel等,被视为不必要的动作。为了简化用户代码,于是推出Functional Programming Model。

引入了新名词:Supplier、Function与Consumer。实际上这几个类可视为Adapter,如果之前已经有存在的Service类,且方法名为各种各样,可以重新包装成Supplier、Function与Consumer,并在固定的方法名:apply/get/accept中调用Service的方法。

Supplier

当在配置文件中注入此类型的Bean,并在spring.cloud.stream.function.definition加入此Bean的名称,SPRING CLOUD STREAM就会帮你生成一个Output  MessageChannel,并连接上此Bean,后续只需要在BINDDING中加入对应的Destination Name,即可向BROKER发消息了。

Consumer

当在配置文件中注入此类型的Bean,并在spring.cloud.stream.function.definition加入此Bean的名称,SPRING CLOUD STREAM就会帮你生成一个Input  MessageChannel,并连接上此Bean,后续只需要在BINDDING中加入对应的Destination Name,即可收到BROKER推送关于此Destination的消息了。

Function

当在配置文件中注入此类型的Bean,并在spring.cloud.stream.function.definition加入此Bean的名称,SPRING CLOUD STREAM就会帮你生成一个Input和Output  MessageChannel,并连接上此Bean,后续只需要在BINDDING中分别对Input和Output MessageChannel加入对应的Destination Name1/Name2,即可收到BROKER推送关于此Destination的消息,也可以向BROKER发消息了。

与SPRING INTEGRATION的整合

如果要对消息进行复杂处理,如拆分消息、聚合消息、IF ELSE消息等,就要借助SPRING INTEGRATION了。

@Bean
    public IntegrationFlow upperCaseFlow(LoanService loanService) {
        return IntegrationFlows
                    //turn this IntegrationFlow as a gateway, here is a Function interface 
                    
//with loadCheckerFunction as bean name
                    .from(LoadCheckerFunction.class, gateway -> gateway.beanName("loadCheckerFunction"))
                    .handle(loanService, "check")
                    .logAndReply(LoggingHandler.Level.WARN);
    }

    public interface LoadCheckerFunction extends Function<Loan, Loan>{

    }

IntegrationFlows.from(Class<?> serviceInterface)是可以将本IntegrationFlow包装成serviceInterface的实现类,如果调用此接口,最终会返回IntegrationFlow最后一个步骤的实体,如果这个serviceInterface是Function的话,刚好和SPRING CLOUD STREAM对接上。

后续在spring.cloud.stream.function.definition加入此Bean的名称loadCheckerFunction,SPRING CLOUD STREAM就会帮你生成一个Input和Output  MessageChannel,并连接上此Bean,再在BINDDING中分别对Input和Output MessageChannel加入对应的Destination Name1/Name2,即可收到BROKER推送关于此Destination的消息,也可以向BROKER发消息。

application.yaml
# This setting can increase or decrease the rate of message production (1000 = 1s)
# spring.cloud.stream.poller.fixed-delay=1000

# This setting can control which function method in our code will be triggered if there are multiple
# spring.cloud.function.definition=supplyLoan

# Give the autogenerated binding a friendlier name

spring:
   application:
      name: loan-check-rabbit
   banner:
      location: classpath:/banner-rabbit.txt
   cloud:
      stream:
         function.definition: loadCheckerFunction
         #BindingProperties
         bindings:
            loadCheckerFunction-in-0:
               destination: queue.pretty.log.messages
               binder: local_rabbit
            loadCheckerFunction-out-0:
               destination: queue.pretty.approved.messages
               binder: local_rabbit
         #BinderProperties
         binders:
            local_rabbit:
               type: rabbit
               environment:
                  spring:
                     rabbitmq:
                        host: 10.80.27.69
                        port: 5672
                        username: guest
                        password: guest
                        virtual-host: my-virtual-host

Reference

https://spring.io/blog/2019/10/25/spring-cloud-stream-and-spring-integration

posted @ 2021-11-10 15:10 paulwong 阅读(399) | 评论 (0)编辑 收藏

在CENTOS LINUX上安装RABBITMQ

安装ERLANG

从这里下载0依赖的ERLANG安装包:
https://github.com/rabbitmq/erlang-rpm/releases 
象这种erlang-23.3.4.8-1.el7.x86_64.rpm含el7的是CENTOS7版本,含el8的是CENTOS8版本,安装脚本
yum install -y erlang-23.3.4.8-1.el7.x86_64.rpm

安装RABBITMQ

下载地址:https://github.com/rabbitmq/rabbitmq-server/releases
安装脚本:yum install -y erlang-23.3.4.8-1.el7.x86_64.rpm

拷贝配置文件

下载配置文件样例:https://github.com/rabbitmq/rabbitmq-server/blob/master/deps/rabbit/docs/rabbitmq.conf.example
粘贴并重命名文件:/etc/rabbitmq/rabbitmq.conf

开启WEB控制台

/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_management

配置guest可远程访问

## Uncomment the following line if you want to allow access to the
## guest user from anywhere on the network.
loopback_users.guest = false

配置开机启动

chkconfig rabbitmq-server on

启动实例

systemctl start rabbitmq-serve
systemctl stop rabbitmq-serve

访问控制台,guest/guest

http://10.80.27.69:15672/#/

Reference
https://www.cnblogs.com/ZhuChangwu/p/14093107.html
https://juejin.cn/post/6933040530519506957

posted @ 2021-11-08 09:27 paulwong 阅读(245) | 评论 (0)编辑 收藏

EVEN DRIVEN - SPRING CLOUD STREAM - SPRING CLOUD微服务的EVEN DRIVEN框架

通常微服务应用之间的通信是通过HTTP调用,吞吐性不建都高,高并发的场景建议使用EVENT DRIVEN的框架,即使用MESSAGE通信。

即A微服务应用将数据发送到MESSAGE BROKER中的某个DESTINATION,此DESTINATION是广播型,非点对点型。B微服务应用订阅此DESTINATION,当有新MESSAGE到达此DESTINATION时,MESSAGE BROKER会将此MESSAGE推送给B应用。所有对此MESSAGE有需要的应用均可订阅,从而收到此MESSAGE。

SPRING CLOUD 中EVENT DRIVEN的框架就是SPRING CLOUD STREAM。其底层是使用SPRING INTEGRATION实现。

SPRING CLOUD STREAM有以下新名词:

  • BINDER:
是对MESSAGE BROKER操作方法的抽象,即应用通过此BINDER操作MESSAGE BROKER。目前只实现了RABITMQ和KAFKA。
  • CHANNEL
MESSAGE从SPRING CLOUD STREAM传给应用或相反是通过CHANNEL传递的,这点和SPRING INTEGRATION是一样的。
  • SOURCE
MESSAGE从应用传给SPRING CLOUD STREAM的CHANNEL,叫@INPUT,包含这种CHANNEL的接口叫SOURCE。
  • SINK
MESSAGE从SPRING CLOUD STREAM传给应用的CHANNEL,叫@OUPUT,包含这种CHANNEL的接口叫SINK。
  • BIDDING
绑定哪个@INPUT或哪个@OUPUT与哪个DESTINATION发送或接收关系的MAPPING。
  • EnableBinding
应用启动时就会建立EnableBinding指定的接口中的CHANNEL
  • 消费者群组
默认下如果同一个应用部署了多个实例,则每个实例都会收到MESSAGE,这时如果设置了消费者群组名称,则同一个名称下的多个实例,只有一个能收到MESSAGE。
  • PARTITION
如果为MESSAGE指定规则,如MESSAGE某个字段值以A开头为一个规则,以B开头为一个规则,那么以A开头的MESSAGE会放到同一个分区中。

这样使用就很简单了,只要取得OUTPUT CHANNEL,就可以发送MESSAGE,将代码关联到INPUT CHANNEL,就能在收到MESSAGE时,相关代码就会被执行。

posted @ 2021-11-05 14:58 paulwong 阅读(209) | 评论 (0)编辑 收藏

OAUTH2 - SPRING SECURITY + KEYCLOAK

     摘要: 根据OAUTH2协议,如果需要用户协助的,则使用authorization_code流程,此时需要用户登录页面、CLIENT SERVER、RESOURCE SERVER和AUTHORIZATION SERVER,其中CLIENT SERVER是通过http调用RESOURCE SERVER的api,AUTHORIZATION SERVER使用现成的KEYCLOAK。如果不需要用户协助的,即SER...  阅读全文

posted @ 2021-11-03 16:58 paulwong 阅读(754) | 评论 (0)编辑 收藏

SPRING BOOT OAUTH2 + KEYCLOAK - service to service call

employee-service调用department-service,如果要按OAUTH2.0流程,只需要提供client-id和client-secrect即可。在KEYCLOAK中引入service-account,即配置该employee-service时,取消standard-flow,同时激活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转成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 @ 2021-10-26 17:06 paulwong 阅读(580) | 评论 (0)编辑 收藏

Nginx代理转发SFTP

https://blog.csdn.net/qq_27127385/article/details/103666143

posted @ 2021-10-15 10:04 paulwong 阅读(352) | 评论 (0)编辑 收藏

使用REST API与KEYCLOAK进行OUATH2协议的登录认证

KEYCLOAK是一套用户、WEB API登录管理,授权管理的WEB应用。
如果要访问受KEYCLOAK保护的REST API服务,则需要夹带一个ACCESS_TOKEN。

前端页面:
  • 前端页面一般是给用户使用的,则需要用户输入在KEYCLOAK中有效的用户名和密码,并提供CALL BAK的URL,提交给KEYCLOAK
    http://10.80.27.69:8180/auth/realms/quickstart/protocol/openid-connect/auth?client_id=app-springboot-confidential&redirect_uri=http://10.80.27.69:8183/&response_type=code&scope=openid
  • 如果KEYCLOAK验证通过,则通知页面重导向回调的URL,并附上code=xxx,此code则是AUTHORIZATION_CODE
    http://10.80.27.69:8183/?session_state=2ad9ab98-6c39-43a8-872f-2112c27b74df&code=3f48ce19-58f9-45d9-8c09-30d492bf4b24.2ad9ab98-6c39-43a8-872f-2112c27b74df.bd7526ef-b1bf-447f-baef-b7dfd6f0df93
  • 回调的URL对应的SERVELET,取得AUTHORIZATION_CODE,并加上client_id和client_secrect,调用KEYLOAK的取ACCESS_TOKEN的HTTP API,取得ACCESS_TOKEN,返回给页面
    http://10.80.27.69:8180/auth/realms/quickstart/protocol/openid-connect/token
    client_id=app-springboot-confidential&client_secret=3acf7692-49cb-4c45-9943-6f3dba512dae&redirect_uri=http://10.80.27.69:8183/&grant_type=authorization_code&code=cc7ac566-90f9-404e-b88e-fa28037b07d1.591311e1-5380-46a2-9363-834f17337922.bd7526ef-b1bf-447f-baef-b7dfd6f0df93
  • 页面保存此ACCESS_TOKEN,就可以调用后台的各种API获取数据
    {
        "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJleHAiOjE2MzQwMjA4ODksImlhdCI6MTYzNDAyMDU4OSwianRpIjoiNDAwOTQ4ZmQtMGU0MS00YWRjLTlhY2MtMzczZWM2NDVhNzM5IiwiaXNzIjoiaHR0cDovLzEwLjgwLjI3LjY5OjgxODAvYXV0aC9yZWFsbXMvcXVpY2tzdGFydCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJkZGVkMDA2YS0xY2QxLTRjODUtOTQ1MS0wMjFlZmY3OTFiMmUiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhcHAtc3ByaW5nYm9vdC1jb25maWRlbnRpYWwiLCJzZXNzaW9uX3N0YXRlIjoiYzRlN2QzYTgtMDg2My00OTAwLTkxZmEtMGExYmFmYmRlNGU3IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYXBwLXNwcmluZ2Jvb3QtY29uZmlkZW50aWFsIjp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudElkIjoiYXBwLXNwcmluZ2Jvb3QtY29uZmlkZW50aWFsIiwiY2xpZW50SG9zdCI6IjEwLjEwLjIwLjU3IiwidXNlcl9uYW1lIjoic2VydmljZS1hY2NvdW50LWFwcC1zcHJpbmdib290LWNvbmZpZGVudGlhbCIsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1hcHAtc3ByaW5nYm9vdC1jb25maWRlbnRpYWwiLCJjbGllbnRBZGRyZXNzIjoiMTAuMTAuMjAuNTcifQ.Ut6aZ6E1d4Esz0gRv2ubxdvrxmGvZLHHZepD5pnGxlqb_yZ4Q82TdGTG0iL4JJn2NH3QAU501dhzzuv6-OT9BUBKP-4ufyKv2DxSvt3GgdN30au5JsATHFyOWuuZGRBd3iWcynf9u3OJnSkHEnrIwRYatgndLzy8dy3AeqF12CI",
        "expires_in": 300,
        "refresh_expires_in": 600,
        "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2MTlhMmJjOS0yMWIwLTRmNGMtODI4OC1kNTJmMjA3OWEzY2EifQ.eyJleHAiOjE2MzQwMjExODksImlhdCI6MTYzNDAyMDU4OSwianRpIjoiYTM0NTQ1MTYtMzc3NC00YmRlLTgzOTMtN2QyMTdkZjdkZmJkIiwiaXNzIjoiaHR0cDovLzEwLjgwLjI3LjY5OjgxODAvYXV0aC9yZWFsbXMvcXVpY2tzdGFydCIsImF1ZCI6Imh0dHA6Ly8xMC44MC4yNy42OTo4MTgwL2F1dGgvcmVhbG1zL3F1aWNrc3RhcnQiLCJzdWIiOiJkZGVkMDA2YS0xY2QxLTRjODUtOTQ1MS0wMjFlZmY3OTFiMmUiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYXBwLXNwcmluZ2Jvb3QtY29uZmlkZW50aWFsIiwic2Vzc2lvbl9zdGF0ZSI6ImM0ZTdkM2E4LTA4NjMtNDkwMC05MWZhLTBhMWJhZmJkZTRlNyIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCJ9.QhjkJBGz5UvwBF7xHM7_V_yjfF0lrA_EWzAVdFf-BRI",
        "token_type": "bearer",
        "not-before-policy": 0,
        "session_state": "c4e7d3a8-0863-4900-91fa-0a1bafbde4e7",
        "scope": "profile email"
    }
  • 这就是authorization_code流程

后端服务:
  • 如果是在一个API中要请求另外一个API的数据,不存在具体用户的情况
  • 需提供如下参数:client_id、client_secrect和grant_type,且grant_type=client_credentials,调用KEYLOAK的取ACCESS_TOKEN的HTTP API,取得ACCESS_TOKEN
    http://10.80.27.69:8180/auth/realms/quickstart/protocol/openid-connect/token
    client_id=app-springboot-confidential&client_secret=3acf7692-49cb-4c45-9943-6f3dba512dae&grant_type=client_credentials
  • 再将此ACCESS_TOKEN以Bearer TOKEN的方式调用别的的API
  • 这就是client_credentials流程

验证Access Token和获取Token元信息:
  • http://10.80.27.69:8180/auth/realms/quickstart/protocol/openid-connect/token/introspect
    client_id=app-springboot-confidential&client_secret=3acf7692-49cb-4c45-9943-6f3dba512dae
  • Access Token无效时返回:
    {
        "active": false
    }

刷新Token:
  • http://10.80.27.69:8180/auth/realms/quickstart/protocol/openid-connect/token
    client_id=app-springboot-confidential&client_secret=3acf7692-49cb-4c45-9943-6f3dba512dae&grant_type=refresh_token&refresh_token=asdfasd
  • 返回
    {
        "access_token": "eyJhbGciOiJSUzI1NiIsIn",
        "expires_in": 300,
        "refresh_expires_in": 1800,
        "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOi",
        "token_type": "Bearer",
        "not-before-policy": 1610728470,
        "session_state": "c1273eb5-f922-420c-b23a-854be9735c1d",
        "scope": "profile email"
    }



Reference:
https://blog.csdn.net/nklinsirui/article/details/112706006

https://www.baeldung.com/?s=keycloak

https://www.doag.org/formes/pubfiles/11143470/2019-NN-Sebastien_Blanc-Easily_Secure_your_Microservices_with_Keycloak-Praesentation.pdf




posted @ 2021-10-12 14:40 paulwong 阅读(787) | 评论 (0)编辑 收藏

Enterprise Architect VS Solution Architect VS Software Architect

  • Enterprise Architect
    定义企业的大概方向
  • Solution Architect
    定义系统使用哪些框架技术
  • Software  Architect
    定义系统行为
  • Technical  Architect
    定义有关部署所使用服务器

https://stackoverflow.com/questions/524941/whats-the-difference-between-solutions-architect-and-applications-architect

https://www.youtube.com/watch?v=zB9WuYE1REI

posted @ 2021-10-11 15:29 paulwong 阅读(170) | 评论 (0)编辑 收藏

SPRING CLOUD CONFIG有界面的配置管理中心




https://dyc87112.github.io/spring-cloud-config-admin/

posted @ 2021-10-07 16:55 paulwong 阅读(297) | 评论 (0)编辑 收藏

开源流程引擎哪个好,如何选型?

https://zhuanlan.zhihu.com/p/369761832

posted @ 2021-09-27 11:05 paulwong 阅读(242) | 评论 (0)编辑 收藏

仅列出标题
共115页: First 上一页 6 7 8 9 10 11 12 13 14 下一页 Last