mirror of
https://github.com/201206030/novel-cloud.git
synced 2025-08-24 17:42:42 +00:00
refactor: 基于 novel 项目 & Spring Cloud 2022 & Spring Cloud Alibaba 2022 重构
This commit is contained in:
@@ -1,76 +1,49 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>novel-cloud</artifactId>
|
||||
<groupId>com.java2nb.novel</groupId>
|
||||
<version>1.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<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>io.github.xxyopen</groupId>
|
||||
<artifactId>novel-cloud</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>novel-monitor</artifactId>
|
||||
<name>novel-monitor</name>
|
||||
<description>微服务管理和监控中心</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<artifactId>novel-monitor</artifactId>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<!-- <plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<version>${docker.maven.plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-image</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<imageName>201206030/${project.artifactId}:${project.version}</imageName>
|
||||
<dockerHost>${docker.host}</dockerHost>
|
||||
<baseImage>java:8</baseImage>
|
||||
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>/</targetPath>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<include>${project.build.finalName}.jar</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</plugin>-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
@@ -1,46 +0,0 @@
|
||||
package com.java2nb.novel.monitor.config;
|
||||
|
||||
import de.codecentric.boot.admin.server.config.AdminServerProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
|
||||
/**
|
||||
* 监控安全配置
|
||||
* @author xiongxiaoyang
|
||||
* @version 1.0
|
||||
* @since 2020/5/27
|
||||
*/
|
||||
@Configuration
|
||||
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
|
||||
private final String adminContextPath;
|
||||
|
||||
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
|
||||
this.adminContextPath = adminServerProperties.getContextPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.authorizeRequests()
|
||||
//配置以公开访问的静态资源和登录页
|
||||
.antMatchers(adminContextPath + "/assets/**").permitAll()
|
||||
.antMatchers(adminContextPath + "/login").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
//配置登录和登出路径
|
||||
.formLogin().loginPage(adminContextPath + "/login").and()
|
||||
.logout().logoutUrl(adminContextPath + "/logout").and()
|
||||
//开启http basic支持,admin-client注册时需要使用
|
||||
.httpBasic().and()
|
||||
.csrf()
|
||||
//开启基于cookie的csrf保护
|
||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
//忽略这些路径的csrf保护以便admin-client注册
|
||||
.ignoringAntMatchers(
|
||||
adminContextPath + "/instances",
|
||||
adminContextPath + "/actuator/**"
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,21 +1,17 @@
|
||||
package com.java2nb.novel.monitor;
|
||||
package io.github.xxyopen.novel.monitor;
|
||||
|
||||
import de.codecentric.boot.admin.server.config.EnableAdminServer;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* 监控服务启动器
|
||||
* @author xiongxiaoyang
|
||||
* @version 1.0
|
||||
* @since 2020/5/27
|
||||
*/
|
||||
@EnableAdminServer
|
||||
@SpringBootApplication
|
||||
@EnableAdminServer
|
||||
@EnableDiscoveryClient
|
||||
public class NovelMonitorApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(NovelMonitorApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(NovelMonitorApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package io.github.xxyopen.novel.monitor.config;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author xiongxiaoyang
|
||||
* @date 2023/3/29
|
||||
*/
|
||||
public class CustomCsrfFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
|
||||
if (csrf != null) {
|
||||
|
||||
Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
|
||||
String token = csrf.getToken();
|
||||
|
||||
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
|
||||
cookie = new Cookie(CSRF_COOKIE_NAME, token);
|
||||
cookie.setPath("/");
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,90 @@
|
||||
package io.github.xxyopen.novel.monitor.config;
|
||||
|
||||
import de.codecentric.boot.admin.server.config.AdminServerProperties;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springframework.http.HttpMethod.DELETE;
|
||||
import static org.springframework.http.HttpMethod.POST;
|
||||
|
||||
/**
|
||||
* Spring Security 配置
|
||||
*
|
||||
* @author xiongxiaoyang
|
||||
* @date 2022/6/8
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class SecuritySecureConfig {
|
||||
|
||||
private final AdminServerProperties adminServer;
|
||||
|
||||
private final SecurityProperties security;
|
||||
|
||||
public SecuritySecureConfig(AdminServerProperties adminServer, SecurityProperties security) {
|
||||
this.adminServer = adminServer;
|
||||
this.security = security;
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
successHandler.setTargetUrlParameter("redirectTo");
|
||||
successHandler.setDefaultTargetUrl(this.adminServer.path("/"));
|
||||
|
||||
http.authorizeHttpRequests((authorizeRequests) -> authorizeRequests //
|
||||
.requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/assets/**"))).permitAll()
|
||||
.requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/actuator/info"))).permitAll()
|
||||
.requestMatchers(new AntPathRequestMatcher(adminServer.path("/actuator/health"))).permitAll()
|
||||
.requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/login"))).permitAll()
|
||||
.dispatcherTypeMatchers(DispatcherType.ASYNC)
|
||||
.permitAll() // https://github.com/spring-projects/spring-security/issues/11027
|
||||
.anyRequest().authenticated())
|
||||
.formLogin((formLogin) -> formLogin.loginPage(this.adminServer.path("/login"))
|
||||
.successHandler(successHandler))
|
||||
.logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
|
||||
.httpBasic(Customizer.withDefaults());
|
||||
|
||||
http.addFilterAfter(new CustomCsrfFilter(), BasicAuthenticationFilter.class)
|
||||
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()).ignoringRequestMatchers(
|
||||
new AntPathRequestMatcher(this.adminServer.path("/instances"), POST.toString()),
|
||||
new AntPathRequestMatcher(this.adminServer.path("/instances/*"), DELETE.toString()),
|
||||
new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))
|
||||
));
|
||||
|
||||
http.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
|
||||
|
||||
return http.build();
|
||||
|
||||
}
|
||||
|
||||
// Required to provide UserDetailsService for "remember functionality"
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
|
||||
UserDetails user = User.withUsername("user").password(passwordEncoder.encode("password")).roles("USER").build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
}
|
22
novel-monitor/src/main/resources/application.yml
Normal file
22
novel-monitor/src/main/resources/application.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
server:
|
||||
port: 8898
|
||||
spring:
|
||||
application:
|
||||
name: novel-monitor
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 192.168.10.110:8848
|
||||
boot:
|
||||
admin:
|
||||
discovery:
|
||||
services:
|
||||
- novel-home-service
|
||||
- novel-news-service
|
||||
- novel-resource-service
|
||||
- novel-book-service
|
||||
- novel-user-service
|
||||
- novel-author-service
|
||||
- novel-search-service
|
||||
- novel-gateway
|
||||
|
@@ -1,10 +0,0 @@
|
||||
spring:
|
||||
application:
|
||||
name: novel-monitor
|
||||
cloud:
|
||||
nacos:
|
||||
config:
|
||||
server-addr: 47.106.243.172:8848
|
||||
file-extension: yml
|
||||
group: ${spring.application.name}
|
||||
namespace: 3960c71a-62ac-4b8f-8c30-bba8e8143a0c
|
Reference in New Issue
Block a user