依赖前置:
4.0.0 com.xiaoshu alibaba-cloud-example 1.0-SNAPSHOT pom 1.8 UTF-8 1.8 1.8 3.8.1 2.6.3 2021.0.1 2021.0.1.0 3.0.0 3.0.3 3.0.3 cloud-gateway cloud-oss cloud-upms cloud-common cloud-auth org.springframework.cloud spring-cloud-starter-bootstrap org.springframework.boot spring-boot-configuration-processor true com.github.ulisesbocchio jasypt-spring-boot-starter ${jasypt.version} org.projectlombok lombok provided org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring-cloud-alibaba.version} pom import ${project.name} src/main/resources true org.springframework.boot spring-boot-maven-plugin ${spring-boot.version} repackage org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.version} ${maven.compiler.target} ${maven.compiler.source} UTF-8 true dev dev true
nacos 源码获取:
- gitlub 下载对应版本
- install 一下
- console 模块为启动模板;
- 其它模块pom引入,console保留源码启动,可以配合开发调试
// 编译install
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
/*** Nacos starter.** @author nacos*/
@SpringBootApplication(scanBasePackages = "com.alibaba.nacos")
@ServletComponentScan
@EnableScheduling
public class Nacos {public static void main(String[] args) {if(initEnv()){SpringApplication.run(Nacos.class, args);}}/*** 单机启动*/private static boolean initEnv() {System.setProperty("nacos.standalone", "true");return true;}}
nacos 服务列表获取示例:
@Data
public class CatalogServiceVo implements Serializable {private Integer count;private List serviceList;
}@Data
public class NacosServiceVo implements Serializable {private String name;private String groupName;private Integer clusterCount;private Integer ipCount;private Integer healthyInstanceCount;private String triggerFlag;
}Object o = catalogServiceV2.pageListService(Constants.DEFAULT_NAMESPACE_ID,StringUtils.EMPTY,StringUtils.EMPTY,1, Integer.MAX_VALUE,StringUtils.EMPTY,false);CatalogServiceVo catalogService = JSONUtil.toBean(o.toString(), CatalogServiceVo.class);
List serviceList = catalogService.getServiceList();
文档: https://sentinelguard.io/zh-cn/
启动:java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar
使用:启动一个服务包,yml配置注册;以接口地址以服务资源,配置限流等规格
简介:分布式服务架构的流量控制组件,主要以流量为切入点,从限流,流量整形、熔断降级、系统负载保护、热点保护等多个维度保证服务稳定性
概念:
流控:
服务降级:
fegin 整合:
系统规则:
网关流控:
sentinel-nacos持久化:
spring:profiles:active: @profiles.active@application:name: @artifactId@cloud:nacos:discovery:server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848}config:server-addr: ${spring.cloud.nacos.discovery.server-addr}file-extension: ymlshared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}sentinel:transport:dashboard: 127.0.0.1:8858#clientIp: 127.0.0.1 #服务与sentinel 不在同一服务器时需:指定当前服务ip#关闭链路收敛,链路限流web-context-unify: false#规则持久化datasource:flow-rule:nacos:server-addr: 127.0.0.1:8848username: nacospaswword: nacosdata-id: cloud-oss-flow-rlue #对应nacos dataId,且nacos要持久化rule-type: flow
@GlobalTransactional
标注则可以com.alibaba.cloud spring-cloud-starter-alibaba-seata
#seata 配置
seata:registry:type: nacosnacos:server-addr: 127.0.0.1:8848application: seata-serverusername: nacospassword: nacosgroup: SEATA_GROUPconfig:type: nacosnacos:server-addr: 127.0.0.1:8848username: nacospassword: nacosgroup: SEATA_GROUPtx-service-group: my_test_tx_group
nacos
获取服务列表,根据文档注解
获取对应接口信息server:port: 9999spring:application:name: @artifactId@profiles:active: @profiles.active@cloud:nacos:discovery:server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848}config:server-addr: ${spring.cloud.nacos.discovery.server-addr}file-extension: ymlsentinel:transport:dashboard: 127.0.0.1:8858gateway:discovery:locator:enabled: trueroutes:- id: cloud-auth-routeuri: lb://cloud-authpredicates:- Path=/auth/**filters:- StripPrefix=1- id: cloud-oss-biz-routeuri: lb://cloud-oss-bizpredicates:- Path=/oss/**filters:- StripPrefix=1- id: cloud-upms-biz-routeuri: lb://cloud-upms-bizpredicates:- Path=/upms/**filters:- StripPrefix=1
本地集成
-javaagent:D:\java_project\alibaba-cloud-example\environment\skywalking9.0-8.10\apache-skywalking-apm-bin\skywalking-agent\skywalking-agent.jar-Dskywalking.agent.service_name=cloud-gateway-Dskywalking.collector.backend_service=127.0.0.1:11800
org.apache.skywalking apm-toolkit-trace 8.10.0 org.apache.skywalking apm-toolkit-logback-1.x 8.10.0
通用security模块
,讲yml配置的忽略路径、以及忽略鉴权注解标注的controller、接口,对应路径注册入security中 registry.antMatchers(HttpMethod.valueOf(method), strings.get(0)).permitAll();
fegin调用
,需要配置请求头,防止微服务内调用鉴权失败@Configuration
public class FeignOauth2RequestInterceptor implements RequestInterceptor {private final String AUTHORIZATION_HEADER = "Authorization";private final String BEARER_TOKEN_TYPE = "Bearer";@Overridepublic void apply(RequestTemplate requestTemplate) {SecurityContext securityContext = SecurityContextHolder.getContext();Authentication authentication = securityContext.getAuthentication();if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) {OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();requestTemplate.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));}}
}
@Configuration
public class FeignRequestConfiguration {@Beanpublic RequestInterceptor requestInterceptor() {return new FeignOauth2RequestInterceptor();}
}
- 针对各个客户端认证,implements ClientDetailsService 配置对应的认证方式
@Component
public class CloudClientDetailsServiceImpl implements ClientDetailsService {@Resourceprivate SysOauthClientDetailsFegin sysOauthClientDetailsFegin;@Resourceprotected PasswordEncoder passwordEncoder;@Overridepublic ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {BaseClientDetails target = new BaseClientDetails();SysOauthClientDetails param = new SysOauthClientDetails().setClientId(s);//fegin调用,获取对应 客户端信息SysOauthClientDetails oauthClientDetails = sysOauthClientDetailsFegin.getByClientId(param).getData();if (oauthClientDetails==null){throw new SecurityException("未找到应用信息!");}setClient(target, oauthClientDetails);return target;}/*** 赋值客户端信息* @param target target* @param oauthClientDetails 客户端数据*/private void setClient(BaseClientDetails target, SysOauthClientDetails oauthClientDetails) {target.setClientId(oauthClientDetails.getClientId());target.setClientSecret(passwordEncoder.encode(oauthClientDetails.getClientSecret()));if (ArrayUtil.isNotEmpty(oauthClientDetails.getAuthorizedGrantTypes())) {target.setAuthorizedGrantTypes(Arrays.asList(oauthClientDetails.getAuthorizedGrantTypes().split(",")));}if (StrUtil.isNotBlank(oauthClientDetails.getAuthorities())) {target.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(oauthClientDetails.getAuthorities()));}if (StrUtil.isNotBlank(oauthClientDetails.getResourceIds())) {target.setResourceIds(StringUtils.commaDelimitedListToSet(oauthClientDetails.getResourceIds()));}if (StrUtil.isNotBlank(oauthClientDetails.getWebServerRedirectUri())) {target.setRegisteredRedirectUri(StringUtils.commaDelimitedListToSet(oauthClientDetails.getWebServerRedirectUri()));}if (StrUtil.isNotBlank(oauthClientDetails.getScope())) {target.setScope(StringUtils.commaDelimitedListToSet(oauthClientDetails.getScope()));}if (StrUtil.isNotBlank(oauthClientDetails.getAutoapprove())) {target.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(oauthClientDetails.getAutoapprove()));}if (oauthClientDetails.getAccessTokenValidity() != null) {target.setAccessTokenValiditySeconds(oauthClientDetails.getAccessTokenValidity());}if (oauthClientDetails.getRefreshTokenValidity() != null) {target.setRefreshTokenValiditySeconds(oauthClientDetails.getRefreshTokenValidity());}}
}
认证服务器配置:
/*** @author xiaoshu* @description 认证服务器配置* 配置token存储* 配置第三方应用* @date 2022年11月13日 12:44*/
@ConditionalOnProperty(prefix = "auth",name = "method",havingValue = "redis")
@Configuration
@EnableAuthorizationServer
//@EnableResourceServer //资源服务器,获取资源前不需要登录,携带token就可以了
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法级别权限
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Resourceprivate RedisConnectionFactory redisConnection;@Resourceprotected PasswordEncoder passwordEncoder;/*** 注入认证管理器*/@Resourceprivate AuthenticationManager authenticationManager;@Beanpublic TokenStore tokenStore(){return new RedisTokenStore(redisConnection);}@Resourceprivate ClientDetailsService cloudClientDetailsServiceImpl;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(cloudClientDetailsServiceImpl);}/*** 配置第三方应用 "authorization_code", "password", "client_credentials", "implicit", "refresh_token"* 1. code吗授权 authorization_code* 2. 静默授权 implicit* 3. 密码授权 (特别信任第三方应用) password* 4. 客户端授权 (直接通过浏览器就能获取token) client_credentials* @param clients* @throws Exception*//*@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory()//code授权.withClient("web").secret(passwordEncoder.encode("web-secret")).scopes("all") //配置第三方应用的业务作用域.authorizedGrantTypes("authorization_code") //授权类型.accessTokenValiditySeconds(7200).redirectUris("https://www.baidu.com").and()//静默授权.withClient("wx").secret(passwordEncoder.encode("wx")).scopes("all").authorizedGrantTypes("implicit").accessTokenValiditySeconds(3600).redirectUris("https://www.baidu.com").and()//密码授权, 这里要查询数据库用户,密码.withClient("admin").secret(passwordEncoder.encode("admin")).scopes("all").authorizedGrantTypes("password").accessTokenValiditySeconds(3600).redirectUris("https://www.baidu.com").and()//客户端授权.withClient("client").secret(passwordEncoder.encode("client-secert")).scopes("all").authorizedGrantTypes("client_credentials").accessTokenValiditySeconds(500).redirectUris("https://www.baidu.com");}*//*** 需要暴露授权服务给token存储* 暴露授权服务器给认证管理器* @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);}
}
# token 校检
security:oauth2:resource:#相当于拿token换取用户信息user-info-uri: http://localhost:3000/getUserInfo
授权码模式
localhost:3000/oauth/authorize?response_type=code&client_id=web&state=sxt&redirect_uri=https://www.baidu.com
post
localhost:3000/outh/token?grant_type=authorization_code&code=iXB5jU&redirect_uri=https://www.baidu.comhead: Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码){
"access_token": "xxx",
"token_type": "bearer",
"expires_in": 7199,
"scope": "all"
}
静默授权模式
localhost:3000/oauth/authorize?response_type=token&client_id=wx&state=sxt&redirect_uri=https://www.baidu.com确认授权后,直接返回token:https://www.baidu.com/#access_token=xxx&token_type=bearer&state=sxt&expires_in=3599&scope=all
密码授权模式
postlocalhost:3000/oauth/token?grant_type=password&username=name&password=pwdhead: Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)
客户端授权模式
postlocalhost:3000/oauth/token?grant_type=client_credentialshead: Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)
com.github.xiaoymin knife4j-spring-boot-starter ${knife4j.version} io.springfox springfox-boot-starter ${swagger.fox.version}
@Configuration
@EnableOpenApi //注解启动用Swagger的使用,同时在配置类中对Swagger的通用参数进行配置
public class Swagger3Config implements EnvironmentAware {private String applicationName;private String applicationDescription;@Beanpublic Docket createRestApi(){//返回文档概要信息return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any()).build().globalRequestParameters(getGlobalRequestParameters()).globalResponses(HttpMethod.GET,getGlobalResponseMessage()).globalResponses(HttpMethod.POST,getGlobalResponseMessage());}/*** 生成接口信息,包括标题,联系人等* @return ApiInfo*/private ApiInfo apiInfo() {return new ApiInfoBuilder().title(applicationName+"接口文档").description(applicationDescription).contact(new Contact("小树","http://www.baidu.com","2810030998@qq.com")).version("1.0").build();}/*** 封装全局通用参数* @return List*/private List getGlobalRequestParameters() {List parameters=new ArrayList<>();RequestParameter headToken = new RequestParameterBuilder().name("Authorization").description("Bearer xxxx").required(true).in(ParameterType.HEADER).query(q -> q.model(m -> m.scalarModel((ScalarType.STRING)))).required(Boolean.FALSE).build();parameters.add(headToken);return parameters;}/*** 封装通用相应信息* @return List*/private List getGlobalResponseMessage() {List responseList=new ArrayList<>();responseList.add(new ResponseBuilder().code("404").description("未找到资源").build());return responseList;}@Beanpublic WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier,ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {List> allEndpoints = new ArrayList<>();Collection webEndpoints = webEndpointsSupplier.getEndpoints();allEndpoints.addAll(webEndpoints);allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());String basePath = webEndpointProperties.getBasePath();EndpointMapping endpointMapping = new EndpointMapping(basePath);boolean shouldRegisterLinksMapping = webEndpointProperties.getDiscovery().isEnabled() &&(org.springframework.util.StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);}@Overridepublic void setEnvironment(Environment environment) {this.applicationDescription = environment.getProperty("spring.application.description");this.applicationName = environment.getProperty("spring.application.name");}
}
spring:mvc:pathmatch:matching-strategy: ANT_PATH_MATCHER #整合swagger时 springboot2.6.x如果不加该配置会报错redis:host: 127.0.0.1password: # token 校检
security:oauth2:resource:#相当于拿token换取用户信息user-info-uri: http://localhost:3000/token/userclient:ignore-urls:- /v2/api-docs springfox:documentation:swagger-ui:enabled: true # false关闭swagger-ui界面 但不关闭openapi
上一篇:数据结构|绪论
下一篇:第一章 认识Python