第四篇:Nacos Server 详探

Posted 重塑之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第四篇:Nacos Server 详探相关的知识,希望对你有一定的参考价值。

上文我们在参考源码样例的基础上( ),成功启动了自己的Nacos Server,本片文章我们在上一篇的基础上,继续详细步骤,来理解Nacos Server 使用的步骤和每部分的功能,为下一步自己的封装做好准备。
设置maven
我们先做好maven配置,在idea中,File-->Settings

在settings.xml中,我们修改两个地方:
1、设置自己maven仓库位置,默认是C盘
在localRepository节点中修改自己想存放的位置(这里存放的是项目依赖的jar包
<localRepository>D:Toolsmaven_repo</localRepository>

第四篇:Nacos Server 详探

1、修改仓库源
在mirrors节点中添加
 <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>

第四篇:Nacos Server 详探


创建项目
在idea中 File-->New-->Project

第四篇:Nacos Server 详探

第四篇:Nacos Server 详探

第四篇:Nacos Server 详探

第四篇:Nacos Server 详探

创建完毕,项目结构:

第四篇:Nacos Server 详探

启动NacosApplication.java

"C:Program FilesJavajdk1.8.0_111injava.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:57519,suspend=y,server=n -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:C:Usersack_AppDataLocalJetBrainsIntelliJIdea2020.1captureAgentdebugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_111jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_111jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_111jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_111jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_111jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_111jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_111jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_111jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_111jrelibext
ashorn.jar;C:Program FilesJavajdk1.8.0_111jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_111jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_111jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_111jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_111jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_111jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_111jrelibjce.jar;C:Program FilesJavajdk1.8.0_111jrelibjfr.jar;C:Program FilesJavajdk1.8.0_111jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_111jrelibjsse.jar;C:Program FilesJavajdk1.8.0_111jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_111jrelibplugin.jar;C:Program FilesJavajdk1.8.0_111jrelib
esources.jar;C:Program FilesJavajdk1.8.0_111jrelib
t.jar;D:ProjectWork
eims
acos	argetclasses;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter-web2.2.6.RELEASEspring-boot-starter-web-2.2.6.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter2.2.6.RELEASEspring-boot-starter-2.2.6.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot2.2.6.RELEASEspring-boot-2.2.6.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-autoconfigure2.2.6.RELEASEspring-boot-autoconfigure-2.2.6.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter-logging2.2.6.RELEASEspring-boot-starter-logging-2.2.6.RELEASE.jar;D:Toolsmaven_repochqoslogbacklogback-classic1.2.3logback-classic-1.2.3.jar;D:Toolsmaven_repochqoslogbacklogback-core1.2.3logback-core-1.2.3.jar;D:Toolsmaven_repoorgapachelogginglog4jlog4j-to-slf4j2.12.1log4j-to-slf4j-2.12.1.jar;D:Toolsmaven_repoorgapachelogginglog4jlog4j-api2.12.1log4j-api-2.12.1.jar;D:Toolsmaven_repoorgslf4jjul-to-slf4j1.7.30jul-to-slf4j-1.7.30.jar;D:Toolsmaven_repojakartaannotationjakarta.annotation-api1.3.5jakarta.annotation-api-1.3.5.jar;D:Toolsmaven_repoorgyamlsnakeyaml1.25snakeyaml-1.25.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter-json2.2.6.RELEASEspring-boot-starter-json-2.2.6.RELEASE.jar;D:Toolsmaven_repocomfasterxmljacksoncorejackson-databind2.10.3jackson-databind-2.10.3.jar;D:Toolsmaven_repocomfasterxmljacksoncorejackson-annotations2.10.3jackson-annotations-2.10.3.jar;D:Toolsmaven_repocomfasterxmljacksoncorejackson-core2.10.3jackson-core-2.10.3.jar;D:Toolsmaven_repocomfasterxmljacksondatatypejackson-datatype-jdk82.10.3jackson-datatype-jdk8-2.10.3.jar;D:Toolsmaven_repocomfasterxmljacksondatatypejackson-datatype-jsr3102.10.3jackson-datatype-jsr310-2.10.3.jar;D:Toolsmaven_repocomfasterxmljacksonmodulejackson-module-parameter-names2.10.3jackson-module-parameter-names-2.10.3.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter-tomcat2.2.6.RELEASEspring-boot-starter-tomcat-2.2.6.RELEASE.jar;D:Toolsmaven_repoorgapache	omcatembed	omcat-embed-core9.0.33	omcat-embed-core-9.0.33.jar;D:Toolsmaven_repoorgapache	omcatembed	omcat-embed-el9.0.33	omcat-embed-el-9.0.33.jar;D:Toolsmaven_repoorgapache	omcatembed	omcat-embed-websocket9.0.33	omcat-embed-websocket-9.0.33.jar;D:Toolsmaven_repoorgspringframeworkootspring-boot-starter-validation2.2.6.RELEASEspring-boot-starter-validation-2.2.6.RELEASE.jar;D:Toolsmaven_repojakartavalidationjakarta.validation-api2.0.2jakarta.validation-api-2.0.2.jar;D:Toolsmaven_repoorghibernatevalidatorhibernate-validator6.0.18.Finalhibernate-validator-6.0.18.Final.jar;D:Toolsmaven_repoorgjbossloggingjboss-logging3.4.1.Finaljboss-logging-3.4.1.Final.jar;D:Toolsmaven_repocomfasterxmlclassmate1.5.1classmate-1.5.1.jar;D:Toolsmaven_repoorgspringframeworkspring-web5.2.5.RELEASEspring-web-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-beans5.2.5.RELEASEspring-beans-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-webmvc5.2.5.RELEASEspring-webmvc-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-aop5.2.5.RELEASEspring-aop-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-context5.2.5.RELEASEspring-context-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-expression5.2.5.RELEASEspring-expression-5.2.5.RELEASE.jar;D:Toolsmaven_repomysqlmysql-connector-java8.0.19mysql-connector-java-8.0.19.jar;D:Toolsmaven_repoorgslf4jslf4j-api1.7.30slf4j-api-1.7.30.jar;D:Toolsmaven_repoorgspringframeworkspring-core5.2.5.RELEASEspring-core-5.2.5.RELEASE.jar;D:Toolsmaven_repoorgspringframeworkspring-jcl5.2.5.RELEASEspring-jcl-5.2.5.RELEASE.jar;D:Program FilesJetBrainsIntelliJ IDEA 2020.1.1libidea_rt.jar" com.reims.main.nacos.NacosApplicationConnected to the target VM, address: '127.0.0.1:57519', transport: 'socket'
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ ( ( )\___ | '_ | '_| | '_ / _` | \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.6.RELEASE)
2020-05-01 12:22:08.223 INFO 2316 --- [ main] com.reims.main.nacos.NacosApplication : Starting NacosApplication on DESKTOP-MBI0KTI with PID 2316 (D:ProjectWork eims acos argetclasses started by wei in D:ProjectWork eims acos)2020-05-01 12:22:08.227 INFO 2316 --- [ main] com.reims.main.nacos.NacosApplication : No active profile set, falling back to default profiles: default2020-05-01 12:22:08.933 INFO 2316 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)2020-05-01 12:22:08.940 INFO 2316 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]2020-05-01 12:22:08.940 INFO 2316 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33]2020-05-01 12:22:08.997 INFO 2316 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext2020-05-01 12:22:08.997 INFO 2316 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 729 ms2020-05-01 12:22:09.116 INFO 2316 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'2020-05-01 12:22:09.241 INFO 2316 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''2020-05-01 12:22:09.243 INFO 2316 --- [ main] com.reims.main.nacos.NacosApplication : Started NacosApplication in 1.356 seconds (JVM running for 2.355)

添加nacos 相关jar包引用:

<?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 https://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.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.reims.main</groupId> <artifactId>nacos</artifactId> <version>0.0.1-SNAPSHOT</version> <name>nacos</name> <description>Demo project for Spring Boot</description>
<properties> <java.version>1.8</java.version> <nacos.version>1.2.1</nacos.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<!-- Nacos Server 相关配置 -->
<dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-config</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-core</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-naming</artifactId> <version>${nacos.version}</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.10.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.10.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.10.5</version> <scope>runtime</scope> </dependency>
<!-- Nacos Server END -->
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.1.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
</project>

前端我们先直接复用,copy源码中static 目录 到resources 目录下

第四篇:Nacos Server 详探

此时启动项目即可访问 http://localhost:8080,但是无法登录:

第四篇:Nacos Server 详探


在application.properties 中添加端口和访问域:

# springserver.servlet.context-path=/nacosserver.port=9000

实现功能

把源码中的代码实现复制到项目中(我尝试了最小构建,只复制某一个方法,但是发现nacos-config 依赖了很多东西,比较麻烦,所以干脆直接先复制过来。目前我们没有基于更深一层的源码构建,只能先这样了),
在修改启动类注解,增加nacos的扫描路径:
@SpringBootApplication(scanBasePackages=("com.reims.main,com.alibaba.nacos"))

第四篇:Nacos Server 详探

启动参数中添加单机启动:

-Dnacos.standalone=true

第四篇:Nacos Server 详探

此时启动项目,报错:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.2020-05-01 23:06:43.745 ERROR 18756 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configController' defined in URL [jar:file:/D:/Tools/maven_repo/com/alibaba/nacos/nacos-config/1.2.1/nacos-config-1.2.1.jar!/com/alibaba/nacos/config/server/controller/ConfigController.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configSubService' defined in URL [jar:file:/D:/Tools/maven_repo/com/alibaba/nacos/nacos-config/1.2.1/nacos-config-1.2.1.jar!/com/alibaba/nacos/config/server/service/ConfigSubService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverListService': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'useAddressServer' in value "${useAddressServer}" at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) at com.reims.main.nacos.NacosApplication.main(NacosApplication.java:11)Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configSubService' defined in URL [jar:file:/D:/Tools/maven_repo/com/alibaba/nacos/nacos-config/1.2.1/nacos-config-1.2.1.jar!/com/alibaba/nacos/config/server/service/ConfigSubService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverListService': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'useAddressServer' in value "${useAddressServer}" at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1290) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1210) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ... 19 common frames omittedCaused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverListService': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'useAddressServer' in value "${useAddressServer}" at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1290) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1210) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ... 33 common frames omittedCaused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'useAddressServer' in value "${useAddressServer}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178) at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124) at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236) at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175) at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:909) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1231) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1210) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ... 45 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:55865', transport: 'socket'
Process finished with exit code 1
在配置文件添加
useAddressServer=true
再次启动即可成功,访问:http://localhost:9000/nacos/

第四篇:Nacos Server 详探

输入nacos/nacos 即可登录:

第四篇:Nacos Server 详探

在配置文件添加数据库配置,登录成功后即可看到我们已有的配置:

第四篇:Nacos Server 详探

登录流程详探

篇幅有限,今天先仅跟踪这一个流程。
实现登陆的类为: UserController.java  中的login方法:
 @PostMapping("/login") public Object login(@RequestParam String username, @RequestParam String password,                        HttpServletResponse response, HttpServletRequest request) throws AccessException { if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {            NacosUser user = (NacosUser) authManager.login(request); response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, NacosAuthConfig.TOKEN_PREFIX + user.getToken());
JSONObject result = new JSONObject(); result.put(Constants.ACCESS_TOKEN, user.getToken()); result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds()); result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin()); return result;        } // 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationToken        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); RestResult<String> rr = new RestResult<String>(); try { //通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象 Authentication authentication = authenticationManager.authenticate(authenticationToken); //将 Authentication 绑定到 SecurityContext SecurityContextHolder.getContext().setAuthentication(authentication); //生成Token String token = jwtTokenUtils.createToken(authentication); //将Token写入到Http头部 response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token); rr.setCode(200); rr.setData("Bearer " + token); return rr; } catch (BadCredentialsException authentication) { rr.setCode(401); rr.setMessage("Login failed"); return rr; } }
可以看出,在if中判断了某个条件,形成了两种校验的方法。if中成立的条件是:配置文件中添加了以下两个参数,
nacos.core.auth.system.type=nacosnacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

目前发现的区别在于使用以上配置时,生成tocken时会使用这个key和userName进行计算生成Tocken:

/** * Create token * * @param authentication auth info * @return token */ public String createToken(Authentication authentication) { return createToken(authentication.getName());    } public String createToken(String userName) {
long now = (new Date()).getTime();
Date validity; validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder() .setClaims(claims) .setExpiration(validity) .signWith(SignatureAlgorithm.HS256, authConfigs.getSecretKey()) .compact(); }

未使用时,是直接生成的:

String token = jwtTokenUtils.createToken(authentication);
 /** * Create token * * @param authentication auth info * @return token */ public String createToken(Authentication authentication) { /** * Current time */ long now = (new Date()).getTime(); /** * Validity date */ Date validity; validity = new Date(now + this.tokenValidityInMilliseconds);
/** * create token */ return Jwts.builder() .setSubject(authentication.getName()) .claim(AUTHORITIES_KEY, "") .setExpiration(validity) .signWith(secretKey, SignatureAlgorithm.HS256) .compact(); }

举例:

使用nacos.core.auth.system.type使生成的tocken为:

第四篇:Nacos Server 详探

不使用是生成tocken为:

第四篇:Nacos Server 详探

可以看出,生成的方式明显是不一样的,第一种的更安全一些。

我们详细看下两种验证的方式:

第一种:

首先进入authManager.login 开始处理

第四篇:Nacos Server 详探

通过resolveToken(req)来进行校验和生成Tocken


 @Override public User login(Object request) throws AccessException { HttpServletRequest req = (HttpServletRequest) request; String token = resolveToken(req); if (StringUtils.isBlank(token)) { throw new AccessException("user not found!"); }
try { tokenManager.validateToken(token); } catch (ExpiredJwtException e) { throw new AccessException("token expired!"); } catch (Exception e) { throw new AccessException("token invalid!"); }
Authentication authentication = tokenManager.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication);
String username = authentication.getName(); NacosUser user = new NacosUser(); user.setUserName(username); user.setToken(token); List<RoleInfo> roleInfoList = roleService.getRoles(username); if (roleInfoList != null) { for (RoleInfo roleInfo : roleInfoList) { if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) { user.setGlobalAdmin(true); break; } } }
return user; }
/** * Get token from header */ private String resolveToken(HttpServletRequest request) throws AccessException { String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER); if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) { return bearerToken.substring(7); } bearerToken = request.getParameter(Constants.ACCESS_TOKEN); if (StringUtils.isBlank(bearerToken)) { String userName = request.getParameter("username"); String password = request.getParameter("password"); bearerToken = resolveTokenFromUser(userName, password); }
return bearerToken; }    private String resolveTokenFromUser(String userName, String rawPassword) throws AccessException {
try { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userName, rawPassword); authenticationManager.authenticate(authenticationToken); } catch (AuthenticationException e) { throw new AccessException("unknown user!"); }
return tokenManager.createToken(userName); }
最终还是封装 UsernamePasswordAuthenticationToken通过 AuthenticationManager调用了 WebSecurityConfigurerAda的 authenticate方法(该方法调用 AbstractUserDetailsAuthenticationProviderauthenticate)来调用了继承了 UserDetails接口的 NacosUserDetails(需实现 loadUserByUsername方法 来实现数据库的查询
public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (delegate != null) {      //调用AbstractUserDetailsAuthenticationProvider的authenticate return delegate.authenticate(authentication); }
synchronized (delegateMonitor) { if (delegate == null) { delegate = this.delegateBuilder.getObject(); this.delegateBuilder = null; } }
return delegate.authenticate(authentication); }

AbstractUserDetailsAuthenticationProvider的authenticate

然后从userCache中获取继承了UserDetails的services,调用其loadUserByUsername方法实现数据库查询

public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, () -> messages.getMessage( "AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported"));
// Determine username String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
boolean cacheWasUsed = true;    //这里从userCache中获取继承了UserDetails的services UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) { cacheWasUsed = false;
try {      //如果通过名称无法从this.userCache获取,这里进行处理,会进入DaoAuthenticationProvider的retrieveUser方法 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { logger.debug("User '" + username + "' not found");
if (hideUserNotFoundExceptions) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } }
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract"); }
try { preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { // There was a problem, so try again after checking // we're using latest data (i.e. not from the cache) cacheWasUsed = false; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } }
postAuthenticationChecks.check(user);
if (!cacheWasUsed) { this.userCache.putUserInCache(user); }
Object principalToReturn = user;
if (forcePrincipalAsString) { principalToReturn = user.getUsername(); }
return createSuccessAuthentication(principalToReturn, authentication, user); }
DaoAuthenticationProviderretrieveUser方法
 final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { prepareTimingAttackProtection(); try {    //通过这里来加载继承了UserDetails的services,然后调用loadUserByUsername来获取数据 UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username); if (loadedUser == null) { throw new InternalAuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } catch (UsernameNotFoundException ex) { mitigateAgainstTimingAttack(authentication); throw ex; } catch (InternalAuthenticationServiceException ex) { throw ex; } catch (Exception ex) { throw new InternalAuthenticationServiceException(ex.getMessage(), ex); } }


第四篇:Nacos Server 详探

/* * Copyright 1999-2018 Alibaba Group Holding Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.reims.main.nacos.console.security.nacos.users;

import com.alibaba.nacos.config.server.auth.UserPersistService;import com.alibaba.nacos.config.server.model.Page;import com.alibaba.nacos.config.server.model.User;import com.alibaba.nacos.core.auth.AuthConfigs;import com.alibaba.nacos.core.utils.Loggers;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Service;
import java.util.Map;import java.util.concurrent.ConcurrentHashMap;
/** * Custem user service * * @author wfnuser * @author nkorange */@Servicepublic class NacosUserDetailsServiceImpl implements UserDetailsService {
private Map<String, User> userMap = new ConcurrentHashMap<>();
@Autowired private UserPersistService userPersistService;
@Autowired private AuthConfigs authConfigs;
@Scheduled(initialDelay = 5000, fixedDelay = 15000) private void reload() { try { Page<User> users = getUsersFromDatabase(1, Integer.MAX_VALUE); if (users == null) { return; }
Map<String, User> map = new ConcurrentHashMap<>(16); for (User user : users.getPageItems()) { map.put(user.getUsername(), user); } userMap = map; } catch (Exception e) { Loggers.AUTH.warn("[LOAD-USERS] load failed", e); } }
@Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userMap.get(username); if (!authConfigs.isCachingEnabled()) { user = userPersistService.findUserByUsername(username); }
if (user == null) { throw new UsernameNotFoundException(username); } return new NacosUserDetails(user); }
public void updateUserPassword(String username, String password) { userPersistService.updateUserPassword(username, password); }
public Page<User> getUsersFromDatabase(int pageNo, int pageSize) { return userPersistService.getUsers(pageNo, pageSize); }
public User getUser(String username) { User user = userMap.get(username); if (!authConfigs.isCachingEnabled()) { user = getUserFromDatabase(username); } return user; }
public User getUserFromDatabase(String username) { return userPersistService.findUserByUsername(username); }
public void createUser(String username, String password) { userPersistService.createUser(username, password); }
public void deleteUser(String username) { userPersistService.deleteUser(username); }}

到此,生成Tocken完成。在

NacosAuthManager

的login方法中,后续继续获取了角色相关的信息,有代码可知是直接差了数据库,就不在详细描述!


第二种:

第二种方式是直接根据用户名和密码,创建了一个UsernamePasswordAuthenticationToken,然后调用authenticate方法直接进入WebSecurityConfigurerAda的authenticate方法来进行验证,之后的用户名和密码调用数据库验证过程与第一种是一致的。



验证完成后,直接调用jwtTokenUtils.createToken(authentication)来生成Tocken

 public String createToken(Authentication authentication) { /** * Current time */ long now = (new Date()).getTime(); /** * Validity date */ Date validity; validity = new Date(now + this.tokenValidityInMilliseconds);
/** * create token */ return Jwts.builder() .setSubject(authentication.getName()) .claim(AUTHORITIES_KEY, "") .setExpiration(validity) .signWith(secretKey, SignatureAlgorithm.HS256) .compact(); }


        至此,本次登录过程分析完毕,虽然更深的原理没有详细分析,比如Spring security 的验证过程和原理,不过这些不在本篇中详细讲述了,更多问题留待以后具体分析。




如果觉得有用,请点下在看,关注公众号重塑之路,第一时间得到资源推送


以上是关于第四篇:Nacos Server 详探的主要内容,如果未能解决你的问题,请参考以下文章

第四篇 函数

从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)

Kubernetes第四篇:手把手打镜像并运行到k8s容器上(亲测可用)

Kubernetes第四篇:手把手打镜像并运行到k8s容器上(亲测可用)

第四篇,新手注册Consul 服务带token

ABP 异常处理 第四篇