华为云用户手册

  • 解决方案 使用devspore-dcs连接redis。 devspore-dcs会默认创建一个bean名称为createMultiZoneClient的redisConnectionFactory,如果用户没有手动修改这个bean名称的话可以不配置devspore.client-control.caches.xxx.redis-connection-factory-bean-name属性,clientcontrol会自动去寻找createMultiZoneClient的bean。 没有使用devspore-dcs。 此时用户需要手动设置devspore.client-control.caches.xxx.redis-connection-factory-bean-name属性,如果不设置,clientcontrol会自动去寻找createMultiZoneClient的bean,因为没有使用devspore-dcs,所以并不存在bean名称为createMultiZoneClient的redisConnectionFactory,此时就会报如上的图的异常。
  • 源码基本结构说明 spring-boot-huawei内部模块及简介: spring-boot-huawei | |-spring-boot-huawei-dependencies # 该模块为内部模块的依赖模块,主要功能是提供依赖包的版本管理,其他模块的父模块均直接或间接使用此模块,如无特殊,spring-boot-huawei使用统一版本的jar包。 | |-spring-boot-huawei-parent # 该模块以dependencies模块为父模块,使用其提供的依赖版本管理,本身提供一些插件定义及插件版本管理,作为本项目中其他模块的父模块使用 | |-spring-boot-starter-huawei # 核心组件,该组件提供一个基于spring-boot的web项目最基本的起步依赖
  • swagger支持https和认证的方式 支持https 在启动类中加入注解: @OpenAPIDefinition( servers = { @Server( url = "https://coralgeneratorsvr.{Environment}-szv-kunpeng-camp.tools.huawei.com/coralgeneratorsvr", #替换成自己的服务地址 variables = { @ServerVariable( name = "Environment",# 参数定义,可使用{param}取其中的值 allowableValues = {"alpha", "beta", "gamma", "prod"},#参数取值范围 defaultValue = "alpha"), }, description = "CoralGeneratorSvr Environmental Urls"), @Server(url = "http://localhost:8080/coralgeneratorsvr", description = "Local Dev Url") }, info = # 服务描述信息 @Info( title = "CoralGeneratorSvr", version = "v1", description = "Coral Generator Server", contact = @Contact(name = "x00464738", email = "xiaoweimin@huawei.com")))@SpringBootApplication@ComponentScan(value = {"com.huawei.coral", "com.huawei.coral.coralgeneratorsvr", "com.huawei.clouddragon.devuc.sdk.*", "com.huawei.clouddragon.apigateway_client"})@MapperScan("com.huawei.coral.coralgeneratorsvr.mapper")@Slf4jpublic class Application extends SpringBootServletInitializer {...} 支持服务接口认证 新增一个配置类,在配置类中加入以下配置: /** * 在线文档接口认证配置 * * @since 2021-08-12 */@Configuration(proxyBeanMethods = false)public class SwaggerAuthConfig { @Bean public OpenAPI springShopOpenAPI() { return new OpenAPI() .components(new Components() .addSecuritySchemes("xAuthToken", new SecurityScheme() .type(SecurityScheme.Type.APIKEY) //请求认证类型 .name("x-auth-token") //参数名称 .description("sso proxy token: x-auth-token") //API key描述 .in(SecurityScheme.In.HEADER))) //设置API key的存放位置(发送请求时请求头中会带上x-auth-token) .security(Collections.singletonList(new SecurityRequirement().addList("xAuthToken"))) //SecurityRequirement中配置的名称需要与SecuritySchema的名称匹配 .info(new Info().title("AuthDemo") .description("AuthDemo接口文档") .version("0.2.0-RELEASE")); }} 完成以上配置后,在线文档中会多出一个认证按钮: 图1 认证 在未输入认证凭证时,直接访问需要认证的接口会返回需要认证的信息: 图2 返回认证信息 输入认证凭证: 图3 输入认证凭证 图4 认证完成 输入认证凭证后,再次调用接口时会将认证信息以配置的方式同请求内容一同发送。 图5 发送认证信息
  • 解决方案 此报错是因为使用了自定义缓存key的功能,注解中配置了@clientcontrol(rules='xxxx', key='xxxxxx')此处key的解析使用的是标准的spring的spel表达式的解析,如果报了如上错误,需要自行排查el表达式的写法是否正确。 如果实在排查不出来el表达式的问题,用户也可以选择使用自定义类的方式去生成指定的缓存key值@ClientControl(rule = "retryTest", policy = CacheOrder.CACHEFIRST, cacheManagerName = "cacheCaffine",keyGenerator = "myKeyGenerator"),其中,keyGenerator属性配置的就是自定义缓存key生成器的bean名称。 如果用户没有必须自定义缓存key的需求,可以不配置这两个属性,clientcontrol会自动生成缓存key的,生成的规则是:全路径限定名+方法名+参数的sha256,clientcontrol提供了一个公共方法来获取这个key值。ClientControlCommonHandle.getCacheKey(final String className, final String methodName, final Object[] args), 此处是伪代码,方法中传入的是全路径限定类名、方法名和参数集合。
  • 问题描述 运行时报错Request processing failed; nested exception is io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'com.huaweicloud.testclientcontrol.serivce.impl.UserServiceImpl#testFallBack' is OPEN and does not permit further calls。
  • 解决方案 在没有使用自定义降级方法和缓存的时候,原方法如果调用失败会抛出方法原始出的错误。 如果使用了自定义降级方法。 熔断前:自定义降级方法中添加的最后一个异常的参数封装的就是原方法的异常。 熔断后:最后一个异常参数会固定抛出“io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'xxxxx#xxxxx' is OPEN and does not permit further calls”异常。 可以通过这个异常参数找到熔断的原因,如果日志过大,找不到熔断前的日志,可以对异常参数类型做个判断,将CallNotPermittedException异常和其他异常区别打印,这样更方便定位问题。如下所示: public String myFallBack(long sleepTime, Throwable throwable) {if (throwable instanceof CallNotPermittedException) {log.info("clientcontrol call not permited exception ", throwable);} else {log.info("service exception " , throwable);}return "xxxx";} 熔断器的状态变化会打印相应的日志,日志中关键信息如下: 关闭到打开(此时处于熔断状态,方法不可访问):changed state from CLOSED to OPEN。 打开到半开(方法可以访问):changed state from OPEN to HALF_OPEN。 半开到打开(此时处于熔断状态,方法不可访问):changed state from HALF_OPEN to OPEN。 半开到关闭(方法恢复正常,可以访问):changed state from HALF_OPEN to CLOSED。 如果日志中找不到原方法的报错信息,只能找到“io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'xxxxx#xxxxx' is OPEN and does not permit further calls”这种日志,需要排查clientcontrol的配置文件,看是否开启了慢调用熔断,如果开启了慢调用熔断,会出现原方法没有报出异常,也被熔断的现象。慢调用的配置参数如下: devspore: client-control: rules: xxx: fallback: #慢调用时间(超过即为慢调用,单位s,默认60S) slow-call-duration-threshold: 60 #慢调用熔断比例(慢调用数量达到比例则熔断,默认100等于关闭状态) slow-call-rate-threshold: 100
  • 组件说明 为支持及简化项目依赖,spring-boot-starter-huawei中配置了基于springboot的web项目常用的基本功能的依赖支持,目前包含以下常用依赖: 基本的spring环境依赖:使用spring-boot-starter完成对基本的spring环境集成,主要包含spring-core,spring-beans,spring-expression,spring-aop,spring-context,spring-aspects,spring-boot,spring-boot-autoconfigure等。 web项目的依赖:包含web开发所需的spring-web,spring-webmvc模块,处理常用格式json数据所需的jackson-databind等。 服务在线文档生成工具:swagger(v2,v3),springdoc-openapi-ui(jdk8),springdoc-openapi-starter-webmvc-ui(jdk17),有了这些工具后可以为服务接口字段生成openapi在线文档。 yaml文件解析用到的snakeyaml,注解:jakarta.annotation-api。 常用工具类的依赖:lombok,commons-lang,guava。 spring-boot-starter-huawei中默认使用log4j2日志框架,需要根据实际情况确定是否使用该日志框架。
  • 缓存优先 clientcontrol提供了一种名为缓存优先的功能。当使用缓存优先功能时,在执行目标业务代码时,优先会查询缓存,如果缓存存在则返回缓存结果,如果缓存不存在则执行目标业务代码。 当使用缓存优先时clientcontrol的处理逻辑如下: 读取缓存,判断是否是性能缓存。 如果是性能缓存,直接将性能缓存当结果返回。 如果不是性能缓存,执行原方法。 如果原方法执行成功,更新缓存,返回结果。 如果原方法执行失败,返回获取的缓存。 如果一开始没有获取到缓存,会直接将原方法执行失败的异常返回。 性能缓存是clientcontrol自带的一个概念,对应配置参数中的performance-ttl。例如一个缓存的有效时长是10s,那性能缓存可以配置为3s,代表一个逻辑概念,标识缓存的结果离更新缓存的时间更近,不会对实际的缓存产生影响。 具体使用方式如下: pom文件添加依赖。 配置文件,参考下面配置样例。 devspore: client-control: caches: test: ttl: 60000 #此处配置的是缓存的有效时长 performance-ttl: 30000 #此处配置的是一个性能缓存,时长一般低于ttl, 当缓存的时间小于性能缓存时,clientcontrol会直接把性能缓存作为方法返回值返回 type: redis 此处配置的是 缓存类型, 支持 redis/caffine 指定具体缓存类型后,用户需要手动引入相关的依赖 maximum-size: 60000 redis-connection-factory-bean-name: redisConnectionFactory # 当使用redis的时候,需要将redis的连接工厂的bean的名称配置在这里 rules: fallbackTest: # 此处配置的是一个别名,用户可自定义,具体使用地方是在注解上 time-limit: enable: false retry: enable: false fallback: # 默认开启 enable: true # 慢调用时间(超过即为慢调用,单位s,默认60S) slow-call-duration-threshold: 30 # 慢调用熔断比例(慢调用数量达到比例则熔断,默认100等于关闭状态) slow-call-rate-threshold: 100 #失败百分比(触发断路器,默认50%) failure-rate-threshold: 50 #滑动窗口类型(COUNT_BASED/TIME_BASED,数量/时间,默认时间) sliding-window-type: COUNT_BASED #滑动窗口大小(默认100,数量:次/时间:秒) sliding-window-size: 5 #滑动窗口内最小请求数(默认100) 必须满足这个要求,才会触发断路器 不满足,不管失败率多少都不会触发 minimum-number-of-calls: 5 #进入半开所需时间(默认60s,单位ms) wait-duration-in-open-state: 10000 #半开状态允许通过的请求数量,默认10个请求(失败比例达到设置的百分比,断路器继续打开,再次等待进入半开)注:不大于滑动窗口内最小请求数,相对较小的配置优先起作用,所以如果大于滑动窗口最小请求,起作用的就是滑动窗口最小请求数了 permitted-number-of-calls-in-half-open-state: 5 目标方法上添加@ClientControl注解,且policy属性设置为CacheOrder.CACHEFIRST,rule属性选择配置文件中自己定义的rules名称(本示例中使用fallbackTest),cacheManagerName属性选择配置文件中自己定义的caches的名称(本示例使用test)。 @ClientControl(rule = "fallbackTest", policy = CacheOrder.CACHEFIRST, cacheManagerName = "test")public String testClientControlJiangji(Integer id) {int i = 1 / id;return new User(id, "vn", 12).toString();} 父主题: 使用熔断降级功能
  • 解决方案 当程序报出这个错误时,说明使用了熔断功能,且此时方法处于熔断状态(熔断器状态为OPEN)。当访问熔断状态的方法时就会抛出这个异常。 熔断器的状态变化时,clientcontrol会打印出如下的日志: [com.huaweicloud.devspore.clientcontrol.core.ClientControlRegistryComponent] - [ClientControlCircuitBreakerSignal:2024-06-14T10:12:59.268797400+08:00[Asia/Shanghai]: CircuitBreaker 'com.huaweicloud.testclientcontrol.serivce.impl.UserServiceImpl#testFallBack' changed state from CLOSED to OPEN] 熔断器有三个状态: CLOSED:这个状态下,方法可以正常访问。 HALF_OPEN:这个状态下,方法可以正常访问。 OPEN:这个状态下,方法不可以访问。
  • redis故障后clientcontrol的处理逻辑是什么 当clientcontrol的缓存类型配置为redis时,此时clientcontrol相当于是redis的使用方,redis自身的配置(超时时间,重试等)还是服务自己设置的,跟clientcontrol没有关系。 clientcontrol中有两个配置参数cache-consecutive-exception-times和cache-interruption-duration ,具体查看:4.5.5CacheConfig数据结构说明。 cache-consecutive-exception-times:记录缓存连续失败的次数上限(此上限是针对配置的一个缓存策略,devspore.client-control.caches.xxx)(读失败,写失败都会累加这个次数,当调用读成功或写成功一次后,会将这个参数置0),当达到这个上限后clientcontrol会关闭缓存的功能,既不读也不写。 cache-interruption-duration:此参数是控制关闭缓存的时间,当达到缓存连续失败的次数上限后,clientcontrol会关闭缓存功能这个参数配置的时间,时间到了以后会开启缓存功能。 父主题: 常见问题
  • 注意事项 当使用超时功能时,当前方法不能运行在异步线程中,异步会导致超时功能失效。 触发重试的机制是方法抛出异常,不管是什么异常,只要抛出了异常方法就会重试,如果抛出某些异常的时候不想重试,则可以参考配置中的ignore-exceptions,没有的时候此参数可以不配置。 配置中的policy中在提供的两种方式中选择一个即可,当使用Randomized的时候,配置randomized-wait-factor。 当使用Exponential的时候配置exponential-backoff-multiplier。
  • clientcontrol中ttl和performanceTtl的具体含义是什么 Cache配置有两个ttl,一个ttl(可靠性缓存)和一个performanceTtl(性能缓存)。 存在误解这两个为是两个缓存,其实缓存只有一个。 实际给缓存设置的缓存过期时间为ttl配置,缓存存入的时候,连同当前时间一同存入了,取出的时候就可以取出缓存存入时间,通过计算与performanceTtl进行比较得出是否是性能缓存。 父主题: 常见问题
  • 认证配置 在配置文件中加入devspore相关配置,如下: devspore: auth: exclude-paths: GET:/test # 不需要认证的路径 in-header: true #token是否在header中,默认true token-name: X-Auth-Token #token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token oneaccess: ignore-ssl: true #是否校验oneaccess证书 jwt: jwk-set-uri: https://arvymzmajv.huaweicloudoneaccess.com/api/v1/oauth2/keys #对应的oneaccessjwk地址 issuer-uri: https://arvymzmajv.huaweicloudoneaccess.com/api/v1/oauth2 #签发机构 arvymzmajv.huaweicloudoneaccess.com为本文示例中使用的 域名 ,实际应用中请换成自己对应的域名。 添加完后启动项目即可开启对token的认证。
  • 用户自定义拦截插件使用 Entry插件 继承抽象类Processor,实现doProcess接口,可定义多个插件。 插件均需注册为bean。 import com.huawei.devspore.horizon.DataEvent;import com.huawei.devspore.horizon.exception.PluginException;import com.huawei.devspore.horizon.processor.Processor;import org.springframework.stereotype.Component;/** * custom request plugin */@Componentpublic class CustomRequestPlugin extends Processor { @Override public boolean doProcess(DataEvent dataEvent) throws PluginException { // do your code ........ return true; }} 配置文件中多个插件以","分隔,多个插件按配置顺序执行。 evspore: horizon: processors: customRequestPlugin Exit插件 实现Observer接口中observer接口,可定义多个插件。 插件均需注册为bean。 import com.huawei.devspore.horizon.DataEvent;import com.huawei.devspore.horizon.exception.PluginException;import com.huawei.devspore.horizon.subscribe.Observer;import org.springframework.stereotype.Component;/** * custom response plugin */@Componentpublic class CustomResponsePlugin implements Observer { @Override public void observe(DataEvent dataEvent) throws PluginException { // do your code ...... }} 配置文件中多个插件以","分隔,多个插件按配置顺序执行。 devspore: horizon: observers: customResponsePlugin 父主题: 扩展拦截开发指南
  • 配置说明 表1 公共参数说明 参数名称 是否必选 默认值 类型 说明 devspore.security.debug 否 true String 是否为debug模式,debug模式会打印加解密调试信息。 devspore.security.provider 否 com.huaweicloud.devspore.security.crypto.DevSporeSecurityExtFactory String 自动配置时使用的加解密提供方具体工程完整类路径。 表2 jasypt参数 参数名称 是否必选 默认值 类型 说明 devspore.security.provider.jasypt.masterkey.path 是 /devsporesecurity String jasypt masterkey路径。 父主题: devspore-security使用指南
  • 配置说明 表1 参数配置说明 参数名称 是否必选 功能 devspore.auth.in-header false token是否在header中,默认true。 devspore.auth.token-name false token在header中的参数名,inHeader设置为true时生效,默认"X-Auth-Token"。 devspore.auth.oneaccess.ignore-ssl true 是否校验oneaccess证书。 devspore.auth.oneaccess.auth-patterns false 需要认证的路径。 devspore.auth.oneaccess.jwt.jwk-set-uri true 对应的oneaccessjwk地址。 devspore.auth.oneaccess.jwt.issuer-uri true 签发机构。 devspore.auth.oneaccess.jwt.jws-algorithm false 签名算法,默认RS256。 父主题: devspore-auth-oneaccess使用指南
  • 工作原理 引入devspore-auth-starter依赖后,会在SDK内自动注册认证Filter:AuthAuthenticationFilter。 调用业务接口时会自动执行已注册的认证Filter,AuthAuthenticationFilter.doFilterInternal中将通过SPI方式先调用TokenParser的实现类(DefaultTokenParser,用户可自定义)完成token解析。 AuthAuthenticationFilter.doFilterInternal在token解析成功后将解析出的用户信息通过SPI方式调用UserStore的实现类(DefaultUserStore,用户可自定义)存储用户信息供后续业务代码使用。 TokenParser接口介绍详见:TokenParser接口介绍 UserInfo用户信息类介绍详见:UserInfo用户信息类 UserStore接口介绍详见:UserStore接口介绍
  • horizon整体架构 devspore-horizon架构图如下: 图1 架构图 Entry类插件采用的是责任链模式(chain of resposibility),所有的插件按照被注册的顺序依次调用,其中有一个插件抛出异常则整个请求返回失败。 Exit类插件采用的是观察者模式(Observer),所有的插件作为观察者注册,DevSpore运行时库里的Publisher模块同时调用所有的观察者插件(插件可能被并发执行且执行的顺序随机),插件执行的结果不能影响请求返回。
  • 配置说明 表1 配置说明 参数名 是否必须 功能 devspore.auth.exclude-paths false 不需要认证的路径,多个规则用“;”分隔,优先级大于devspore.auth.auth-patterns。 devspore.auth.auth-patterns false 需要认证的路径,多个规则用“;”分隔。 devspore.auth.in-header false token是否在header中,默认true。 devspore.auth.token-name false token在header中的参数名,inHeader设置为true时生效,默认“X-Auth-Token”。
  • 服务优先 clientcontrol提供了一种名为服务优先的功能。当使用服务优先功能时,在执行目标业务代码时,优先执行业务代码并返回,如果业务代码报错则去查询缓存并返回。具体使用方式如下: pom文件添加依赖。 配置文件,参考下面配置样例。 devspore: client-control: caches: test: ttl: 60000 #此处配置的是缓存的有效时长 performance-ttl: 30000 #此处配置的是一个性能缓存,时长一般低于ttl, 当缓存的时间小于性能缓存时,clientcontrol会直接把性能缓存作为方法返回值返回 type: redis 此处配置的是 缓存类型, 支持 redis/caffine 指定具体缓存类型后,用户需要手动引入相关的依赖 maximum-size: 60000 redis-connection-factory-bean-name: redisConnectionFactory # 当使用redis的时候,需要将redis的连接工厂的bean的名称配置在这里 rules: fallbackTest: # 此处配置的是一个别名,用户可自定义,具体使用地方是在注解上 time-limit: enable: false retry: enable: false fallback: # 默认开启 enable: true # 慢调用时间(超过即为慢调用,单位s,默认60S) slow-call-duration-threshold: 30 # 慢调用熔断比例(慢调用数量达到比例则熔断,默认100等于关闭状态) slow-call-rate-threshold: 100 #失败百分比(触发断路器,默认50%) failure-rate-threshold: 50 #滑动窗口类型(COUNT_BASED/TIME_BASED,数量/时间,默认时间) sliding-window-type: COUNT_BASED #滑动窗口大小(默认100,数量:次/时间:秒) sliding-window-size: 5 #滑动窗口内最小请求数(默认100) 必须满足这个要求,才会触发断路器 不满足,不管失败率多少都不会触发 minimum-number-of-calls: 5 #进入半开所需时间(默认60s,单位ms) wait-duration-in-open-state: 10000 #半开状态允许通过的请求数量,默认10个请求(失败比例达到设置的百分比,断路器继续打开,再次等待进入半开)注:不大于滑动窗口内最小请求数,相对较小的配置优先起作用,所以如果大于滑动窗口最小请求,起作用的就是滑动窗口最小请求数了 permitted-number-of-calls-in-half-open-state: 5 目标方法上添加@ClientControl注解,且policy属性设置为CacheOrder.SERVICECALLFIRST,rule属性选择配置文件中自己定义的rules名称(本示例中使用fallbackTest),cacheManagerName属性选择配置文件中自己定义的caches的名称(本示例使用test)。 @ClientControl(rule = "fallbackTest", policy = CacheOrder.SERVICECALLFIRST, cacheManagerName = "test")public String testClientControlJiangji(Integer id) {int i = 1 / id;return new User(id, "vn", 12).toString();} 当使用服务优先时clientcontrol的处理逻辑如下: 执行原方法,如果执行成功,更新缓存,返回结果。如果执行方法失败,获取缓存。 如果成功拿到缓存,则将缓存结果返回。如果没有拿到缓存则将原方法的执行失败异常返回。 父主题: 使用熔断降级功能
  • 认证配置 一般服务配置devspore.auth.exclude-paths与devspore.auth.auth-patterns其中之一即可。 在配置文件中加入devspore相关配置,如下: 示例1:/healthz;/error;/swagger-ui.html;/swagger-ui/**;/oneaccess-docs/**;/api-docs/**;等API无需认证,除此之外所有API均进行认证。 devspore: auth: exclude-paths: /healthz;/error;/swagger-ui.html;/swagger-ui/**;/oneaccess-docs/**;/api-docs/**; # 不需要认证的路径,多个规则用;分隔 in-header: true # token是否在header中,默认true token-name: X-Auth-Token # token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token 示例2:以“/v1/”开头的所有API均进行认证。 devspore: auth: auth-patterns: /v1/** # 需要认证的路径,多个规则用;分隔 in-header: true # token是否在header中,默认true token-name: X-Auth-Token # token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token
  • 实现TokenParser接口示例 import com.huawei.devspore.plugin.spi.authentication.UserInfo;import com.huaweicloud.devspore.auth.commons.spi.TokenParser;import jakarta.servlet.http.HttpServletRequest;import jakarta.servlet.http.HttpServletResponse;import org.springframework.stereotype.Component;@Componentpublic class CustomTokenParser implements TokenParser { /** * 若token定义在header中,可使用该接口,token获取根据配置由devspore-auth获取 * * @param token * @param response * @return UserInfo */ @Override public UserInfo parserToken(String token, HttpServletResponse response) { // 自定义token解析 ...... // 判断token是否过期 ...... UserInfo userInfo = new UserInfo(); // 根据解析后的token信息填充UserInfo对象 ...... return userInfo; } /** * 若token未定义在header中,使用该接口 * * @param request * @param response * @return UserInfo */ @Override public UserInfo parserToken(HttpServletRequest request, HttpServletResponse response) { // 从httpServletRequest获取token ...... // 自定义token解析 ...... // 判断token是否过期 ...... UserInfo userInfo = new UserInfo(); // 根据解析后的token信息填充UserInfo对象 ...... return userInfo; }}
  • 实现UserStore接口 import com.huawei.devspore.plugin.spi.authentication.UserInfo;import com.huawei.devspore.plugin.spi.authentication.UserStore;import org.springframework.stereotype.Component;@Componentpublic class CustomUserStore implements UserStore { @Override public void setUserInfo(UserInfo userInfo) { // 自定义存储用户信息 ...... } @Override public UserInfo getUserInfo() { UserInfo userInfo = new UserInfo(); // 自定义用户信息获取 ...... return userInfo; }}
  • 工作原理 引入devspore-auth-starter依赖后,会在SDK内自动注册认证Filter:AuthAuthenticationFilter。 调用业务接口时会自动执行已注册的认证Filter,AuthAuthenticationFilter.doFilterInternal中将通过SPI方式先调用TokenParser的实现类(DefaultTokenParser,可自定义)完成token解析。 AuthAuthenticationFilter.doFilterInternal在token解析成功后将解析出的用户信息通过SPI方式调用UserStore的实现类(DefaultUserStore,用户可自定义)存储用户信息供后续业务代码使用。
  • TokenParser接口介绍 package com.huaweicloud.devspore.auth.commons.spi;import com.huawei.devspore.plugin.spi.authentication.UserInfo;import jakarta.servlet.http.HttpServletRequest;import jakarta.servlet.http.HttpServletResponse;public interface TokenParser { /** * 根据token解析用户信息 * * @param token * @param response * @return 用户信息 UserInfo */ UserInfo parserToken(String token, HttpServletResponse response); /** * 根据HttpRequest解析用户信息 * * @param httpServletRequest * @param response * @return 用户信息 UserInfo */ UserInfo parserToken(HttpServletRequest httpServletRequest, HttpServletResponse response);} 两个方法,用户选其一实现即可;AuthAuthenticationFilter中通过devspore.auth.in-header配置值(默认true,配置说明详见下文“配置说明”章节)自动调用相应方法。 若token定义在header中,需实现parserToken(String token, HttpServletResponse response)接口,token获取根据配置由devspore-auth-starter获取。 若token未定义在header中,devspore.auth.in-header配置为false,并实现parserToken(HttpServletRequest httpServletRequest, HttpServletResponse response)接口。
  • UserStore接口介绍 package com.huawei.devspore.plugin.spi.authentication;/** * 用户信息接口 */public interface UserStore { /** * 设置用户信息 * @param userInfo */ void setUserInfo(UserInfo userInfo); /** * 获取用户信息 * @return UserInfo */ UserInfo getUserInfo();} AuthAuthenticationFilter.doFilterInternal会在token解析成功后调用setUserInfo(UserInfo userInfo)接口存储用户信息。 后续业务接口鉴权或业务逻辑需要时调用getUserInfo()接口获取当前用户信息。
  • AuthObject对象 AuthObject对象即鉴权客体,被鉴权对象。 表2 AuthObject对象参数说明 参数名称 数据类型 描述 projectId String 被鉴权资源所在的项目id,对于不属于项目的资源,允许为空。 对于非多项目应用(MetaService中tenantModel为null或者TENANT),允许为空。 如果为多项目应用(MetaService中tenantModel值为TENANT_PROJECT),则传入projectId。 resource String 被鉴权资源,不允许为空。 根据MetaBOAuthorizeType不同的值,传入对应值。 ROOT:传入BO对象所在的Root BO的id。 TYPE_LEVEL:传入BO name。 INSTANCE_LEVEL:传入BO对象id。
  • AuthSubject对象 AuthSubject对象即鉴权主体。 表1 AuthSubject对象参数说明 参数名称 数据类型 描述 tenantId String 根据用户所在的租户传值: 对于非多租应用(MetaService中tenantModel为空),允许为空。 如果为多租应用(MetaService中tenantModel值为TENANT或者TENANT_PROJECT),则传入tenantId。 uid String 鉴权主体的user id,不允许为空。
  • 常用约束 表1 常用约束说明 注解 约束说明 @Null 被注释的元素必须为null。 @NotNull 被注释的元素必须不为null。 @AssertTrue 被注释的元素必须为true。 @AssertFalse 被注释的元素必须为false。 @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值。 @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值。 @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值。 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值。 @Size(max=, min=) 被注释的元素的大小必须在指定的范围内。 @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内。 @Past 被注释的元素必须是一个过去的日期。 @Future 被注释的元素必须是一个将来的日期。 @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式。 @NotBlank(message =) 验证字符串非null,且长度必须大于0。 @Email 被注释的元素必须是电子邮箱地址。 @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内。 @NotEmpty 被注释的字符串的必须非空。 @Range(min=,max=,message=) 被注释的元素必须在合适的范围内。
  • 初始化功能 引入initializer接口: 分离初始化逻辑和请求处理逻辑,程序逻辑更清晰,让用户更易写出结构良好,性能更优的代码。 用户函数代码更新时,系统能够保证用户函数的平滑升级,规避应用层初始化冷启动带来的性能损耗。新的函数实例启动后能够自动执行用户的初始化逻辑,在初始化完成后再处理请求。 在应用负载上升,需要增加更多函数实例时,系统能够识别函数应用层初始化的开销,更准确的计算资源伸缩的时机和所需的资源量,让请求延时更加平稳。
共100000条
提示

您即将访问非华为云网站,请注意账号财产安全