Commit ffa894fc by zhangxingmin

Initial commit

parents
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../:\soft\ideaproject\v3\yd-cloud-core\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="yd-common" />
<module name="yd-gateway" />
<module name="yd-auth-core" />
<module name="yd-feign" />
<module name="yd-framework" />
</profile>
</annotationProcessing>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-auth-core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-auth-core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-feign/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-feign/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-framework/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-framework/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-gateway/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yd-gateway/src/main/resources" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="yd-releases" />
<option name="name" value="yd-releases" />
<option name="url" value="http://139.224.145.34:8081/repository/yd-maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://139.224.145.34:8081/repository/yd-maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="yd-snapshots" />
<option name="name" value="yd-snapshots" />
<option name="url" value="http://139.224.145.34:8081/repository/yd-maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://139.224.145.34:8081/repository/maven-public/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
spring:
profiles:
active: test
# active: '@spring.profiles.active@'
---
spring:
profiles: dev
main:
allow-bean-definition-overriding: true
allow-circular-references: true
cloud:
nacos:
# 配置中心
config:
# 命名空间id(此处不用public,因public初始化的空间, id为空) 4e237601-cea8-414d-b7b9-d7adc8cbcf95
namespace: 22f9d61e-9011-4d45-88cb-24f9857e3eec
# nacos的ip地址和端口 120.79.64.17:10848
server-addr: 127.0.0.1:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
file-extension: yml
config-retry-time: 300000
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]:
dataId: linkwe-common.yml
refresh: true
# 发布到注册中心 (如果没有使用可以不配)
discovery:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: ${spring.cloud.nacos.config.namespace}
# nacos的ip地址和端口
server-addr: ${spring.cloud.nacos.config.server-addr}
---
spring:
profiles: test
main:
allow-bean-definition-overriding: true
allow-circular-references: true
cloud:
nacos:
# 配置中心
config:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: d2446fdc-2683-4c82-aa86-61242c61b5cd
# nacos的ip地址和端口
server-addr: 139.224.145.34:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
file-extension: yml
config-retry-time: 300000
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]:
dataId: yd-common.yml
refresh: true
# 发布到注册中心 (如果没有使用可以不配)
discovery:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: ${spring.cloud.nacos.config.namespace}
# nacos的ip地址和端口
server-addr: ${spring.cloud.nacos.config.server-addr}
---
spring:
profiles: prod
main:
allow-bean-definition-overriding: true
allow-circular-references: true
cloud:
nacos:
# 配置中心
config:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: ewscrm
# nacos的ip地址和端口
server-addr: 127.0.0.1:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
file-extension: yml
config-retry-time: 300000
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]:
dataId: linkwe-common.yml
refresh: true
# 发布到注册中心 (如果没有使用可以不配)
discovery:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: ${spring.cloud.nacos.config.namespace}
# nacos的ip地址和端口
server-addr: ${spring.cloud.nacos.config.server-addr}
<?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>
<!-- 继承yd-parent-pom -->
<parent>
<groupId>com.yd</groupId>
<artifactId>yd-parent-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<description>微服务核心组件父模块</description>
<modules>
<module>yd-common</module>
<module>yd-auth-core</module>
<module>yd-gateway</module>
<module>yd-feign</module>
<module>yd-framework</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<version>5.7.8</version> <!-- 与Spring Security版本匹配(2.7.x Boot对应5.7.x Security) -->
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.7.8</version> <!-- 同上,版本需匹配 -->
</dependency>
<!-- JWT 依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-feign</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-framework</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-auth-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.4.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 部署到Nexus -->
<distributionManagement>
<repository>
<id>yd-releases</id>
<url>http://139.224.145.34:8081/repository/yd-project-releases/</url>
</repository>
<snapshotRepository>
<id>yd-snapshots</id>
<url>http://139.224.145.34:8081/repository/yd-project-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<!-- 配置Nexus快照仓库,用于拉取快照版本依赖 -->
<repository>
<id>yd-snapshots</id>
<url>http://139.224.145.34:8081/repository/yd-project-snapshots/</url>
<snapshots>
<enabled>true</enabled> <!-- 允许拉取快照版本 -->
</snapshots>
<releases>
<enabled>false</enabled> <!-- 不启用正式版仓库(按需调整) -->
</releases>
</repository>
</repositories>
</project>
<?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>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yd-auth-core</artifactId>
<name>yd-auth-core</name>
<description>认证授权核心模块</description>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Security OAuth2 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<!-- JWT 依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
</dependency>
<!-- yd-user-service 模块 -->
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-user-service</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package com.yd.auth.core;
import com.yd.common.constant.ServerNameConstants;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@MapperScan("com.yd.**.mapper")
@EnableFeignClients(basePackages = "com.yd.auth.core.**")
public class AuthApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(AuthApplication.class)
.properties("spring.config.name:bootstrap", "config/bootstrap.yml")
.properties("spring.application.name="+ ServerNameConstants.ydAuthCore)
.build().run(args);
System.out.println("(♥◠‿◠)ノ゙ yd-auth-core认证服务启动成功 ლ(´ڡ`ლ)゙ ");
}
}
package com.yd.auth.core.config;
import com.yd.auth.core.security.JwtAuthenticationEntryPoint;
import com.yd.auth.core.security.JwtAuthenticationFilter;
import com.yd.auth.core.security.JwtAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
"/swagger-resources", "/swagger-resources/configuration/security",
"/swagger-ui.html", "/webjars/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
package com.yd.auth.core.controller;
import com.yd.common.result.Result;
import com.yd.auth.core.service.AuthService;
import com.yd.user.service.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/login")
public Result<?> login(@RequestBody Map<String, String> loginRequest) {
String username = loginRequest.get("username");
String password = loginRequest.get("password");
Map<String, String> tokens = authService.login(username, password);
return Result.success(tokens);
}
@PostMapping("/refresh")
public Result<?> refreshToken(@RequestBody Map<String, String> refreshRequest) {
String refreshToken = refreshRequest.get("refreshToken");
Map<String, String> tokens = authService.refreshToken(refreshToken);
return Result.success(tokens);
}
@PostMapping("/register")
public Result<?> register(@RequestBody User user) {
User registeredUser = authService.register(user);
return Result.success(registeredUser);
}
}
package com.yd.auth.core.security;
import com.yd.auth.core.security.JwtAuthenticationToken;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
@Component
public class DummyAuthenticationManager implements ReactiveAuthenticationManager {
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
// 检查是否为 JwtAuthenticationToken 类型
if (authentication instanceof JwtAuthenticationToken) {
String token = (String) authentication.getCredentials();
try {
// 验证令牌有效性(实际项目中应调用 JwtUtils 验证)
if (isValidToken(token)) {
// 从令牌中提取用户名和权限信息
String username = extractUsernameFromToken(token);
List<GrantedAuthority> authorities = extractAuthoritiesFromToken(token);
// 创建已认证的令牌
JwtAuthenticationToken authenticatedToken =
new JwtAuthenticationToken(username, authorities);
authenticatedToken.setDetails(authentication.getDetails());
// return Mono.just(authenticatedToken);
return null;
}
} catch (Exception e) {
return Mono.error(e);
}
}
// 非 JWT 认证请求,返回空
return Mono.empty();
}
// 实际项目中应调用 JwtUtils 验证令牌
private boolean isValidToken(String token) {
// 示例实现,实际应调用 JwtUtils.validateToken(token)
return token != null && !token.isEmpty();
}
// 实际项目中应从令牌中解析用户名
private String extractUsernameFromToken(String token) {
// 示例实现,实际应调用 JwtUtils.getUsernameFromToken(token)
return "test-user";
}
// 实际项目中应从令牌中解析权限
private List<GrantedAuthority> extractAuthoritiesFromToken(String token) {
// 示例实现,实际应调用 JwtUtils.getRolesFromToken(token)
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return authorities;
}
}
package com.yd.auth.core.security;
import com.alibaba.fastjson.JSON;
import com.yd.common.result.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
// 设置响应状态码为401
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
// 设置响应内容类型
response.setContentType("application/json;charset=UTF-8");
// 返回统一的错误响应
Result<?> result = Result.fail(401, "未经授权: " + authException.getMessage());
response.getWriter().write(JSON.toJSONString(result));
}
}
package com.yd.auth.core.security;
import com.yd.auth.core.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
// 从请求头中获取JWT令牌
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateToken(jwt)) {
// 从JWT中获取用户名
String username = jwtUtils.getUsernameFromToken(jwt);
// 加载用户详情
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 创建认证令牌
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 将认证信息设置到SecurityContext中
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
log.error("无法设置用户认证: {}", e.getMessage());
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (headerAuth != null && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
}
package com.yd.auth.core.security;
import com.yd.auth.core.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String token = (String) authentication.getCredentials();
try {
// 验证JWT令牌
if (!jwtUtils.validateToken(token)) {
throw new BadCredentialsException("无效的令牌");
}
// 从令牌中获取用户名
String username = jwtUtils.getUsernameFromToken(token);
// 加载用户详情
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 从令牌中获取角色
List<String> roles = jwtUtils.getRolesFromToken(token);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
// 创建已认证的令牌
JwtAuthenticationToken authenticatedToken =
new JwtAuthenticationToken(userDetails, authorities);
authenticatedToken.setDetails(authentication.getDetails());
return authenticatedToken;
} catch (Exception e) {
throw new BadCredentialsException("认证失败", e);
}
}
@Override
public boolean supports(Class<?> authentication) {
return JwtAuthenticationToken.class.isAssignableFrom(authentication);
}
}
package com.yd.auth.core.security;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import java.util.Collection;
public class JwtAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object principal;
private String credentials;
/**
* 用于未认证的令牌
*/
public JwtAuthenticationToken(String token) {
super(null);
this.principal = token;
this.credentials = token;
setAuthenticated(false);
}
/**
* 用于已认证的令牌
*/
public JwtAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
super.setAuthenticated(true); // must use super, as we override
}
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
credentials = null;
}
}
package com.yd.auth.core.service;
import com.yd.auth.core.security.JwtAuthenticationToken;
import com.yd.user.service.entity.User;
import org.springframework.security.core.Authentication;
import java.util.Map;
public interface AuthService {
/**
* 用户登录
*/
Map<String, String> login(String username, String password);
/**
* 刷新令牌
*/
Map<String, String> refreshToken(String refreshToken);
/**
* 验证令牌
*/
Authentication validateToken(String token);
/**
* 注册新用户
*/
User register(User user);
}
package com.yd.auth.core.service;
import com.yd.user.service.entity.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public interface UserService extends UserDetailsService {
/**
* 根据用户名加载用户详情
*/
@Override
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
/**
* 根据用户名查找用户
*/
User findByUsername(String username);
/**
* 注册新用户
*/
User register(User user);
}
package com.yd.auth.core.service.impl;
import com.yd.auth.core.security.JwtAuthenticationToken;
import com.yd.auth.core.service.AuthService;
import com.yd.auth.core.utils.JwtUtils;
import com.yd.user.service.entity.User;
import com.yd.user.service.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserService userService;
@Override
public Map<String, String> login(String username, String password) {
// 验证用户名和密码
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
);
// 将认证信息设置到SecurityContext中
SecurityContextHolder.getContext().setAuthentication(authentication);
// 获取用户信息
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// 生成JWT令牌
String token = jwtUtils.generateToken(userDetails);
String refreshToken = jwtUtils.generateRefreshToken(userDetails);
// 返回令牌
Map<String, String> result = new HashMap<String, String>();
result.put("token", token);
result.put("refreshToken", refreshToken);
return result;
}
@Override
public Map<String, String> refreshToken(String refreshToken) {
// 验证刷新令牌
if (!jwtUtils.validateToken(refreshToken)) {
throw new RuntimeException("无效的刷新令牌");
}
// 获取用户名
String username = jwtUtils.getUsernameFromToken(refreshToken);
// 加载用户详情
UserDetails userDetails = userService.loadUserByUsername(username);
// 生成新的JWT令牌
String token = jwtUtils.generateToken(userDetails);
// 返回新令牌
Map<String, String> result = new HashMap<String, String>();
result.put("token", token);
result.put("refreshToken", refreshToken);
return result;
}
@Override
public Authentication validateToken(String token) {
JwtAuthenticationToken authentication = new JwtAuthenticationToken(token);
return authenticationManager.authenticate(authentication);
}
@Override
public User register(User user) {
return userService.register(user);
}
}
package com.yd.auth.core.utils;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
@Value("${jwt.refresh-expiration}")
private Long refreshExpiration;
/**
* 生成JWT令牌
*/
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<String, Object>();
// 添加用户角色
claims.put("roles", userDetails.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList()));
return createToken(claims, userDetails.getUsername(), expiration);
}
/**
* 生成刷新令牌
*/
public String generateRefreshToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername(), refreshExpiration);
}
/**
* 创建JWT令牌
*/
private String createToken(Map<String, Object> claims, String subject, Long expirationTime) {
SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expirationTime * 1000))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}
/**
* 解析JWT令牌
*/
public Claims parseToken(String token) {
SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
try {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
throw new RuntimeException("令牌已过期", e);
} catch (UnsupportedJwtException e) {
throw new RuntimeException("不支持的令牌", e);
} catch (MalformedJwtException e) {
throw new RuntimeException("无效的令牌", e);
} catch (SignatureException e) {
throw new RuntimeException("签名验证失败", e);
} catch (IllegalArgumentException e) {
throw new RuntimeException("令牌参数错误", e);
}
}
/**
* 从令牌中获取用户名
*/
public String getUsernameFromToken(String token) {
return parseToken(token).getSubject();
}
/**
* 从令牌中获取过期时间
*/
public Date getExpirationDateFromToken(String token) {
return parseToken(token).getExpiration();
}
/**
* 检查令牌是否过期
*/
public Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* 验证令牌
*/
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
public Boolean validateToken(String token) {
try {
// 解析token
Claims claims = parseToken(token);
// 检查是否过期
return !isTokenExpired(token);
} catch (Exception e) {
return false;
}
}
/**
* 从令牌中获取角色
*/
public List<String> getRolesFromToken(String token) {
Claims claims = parseToken(token);
return claims.get("roles", List.class);
}
/**
* 从令牌中获取指定的声明
*/
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = parseToken(token);
return claimsResolver.apply(claims);
}
}
#Generated by Maven
#Mon Jul 28 18:02:31 CST 2025
version=1.0-SNAPSHOT
groupId=com.yd
artifactId=yd-auth-core
com\yd\auth\core\AuthApplication.class
com\yd\auth\core\security\JwtAuthenticationToken.class
com\yd\auth\core\service\impl\AuthServiceImpl.class
com\yd\auth\core\service\AuthService.class
com\yd\auth\core\service\UserService.class
com\yd\auth\core\controller\AuthController.class
com\yd\auth\core\security\DummyAuthenticationManager.class
com\yd\auth\core\security\JwtAuthenticationEntryPoint.class
com\yd\auth\core\security\JwtAuthenticationProvider.class
com\yd\auth\core\config\SecurityConfig.class
com\yd\auth\core\security\JwtAuthenticationFilter.class
com\yd\auth\core\utils\JwtUtils.class
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\security\JwtAuthenticationToken.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\security\DummyAuthenticationManager.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\controller\AuthController.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\service\UserService.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\utils\JwtUtils.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\service\AuthService.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\AuthApplication.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\security\JwtAuthenticationProvider.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\security\JwtAuthenticationFilter.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\config\SecurityConfig.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\security\JwtAuthenticationEntryPoint.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-auth-core\src\main\java\com\yd\auth\core\service\impl\AuthServiceImpl.java
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />
\ No newline at end of file
<?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>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yd-common</artifactId>
<name>yd-common</name>
<description>公共组件模块</description>
<dependencies>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>
package com.yd.common.constant;
/**
* 系统服务名称
*/
public class ServerNameConstants {
/**
* yd-gateway网关服务名称
*/
public static String ydGateway="yd-gateway";
/**
* yd-auth-core认证授权核心模块服务名称
*/
public static String ydAuthCore="yd-auth-core";
/**
* yd-user-api用户接口模块服务名称
*/
public static String ydUserApi="yd-user-api";
/**
* yd-scrm-api接口模块服务名称
*/
public static String ydScrmApi="yd-scrm-api";
}
package com.yd.common.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 登录请求参数
*/
@Data
public class LoginDTO {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
}
package com.yd.common.dto;
import lombok.Data;
/**
* JWT令牌返回结果
*/
@Data
public class TokenDTO {
private String accessToken; // 访问令牌
private String refreshToken; // 刷新令牌
private long expireTime; // 过期时间(秒)
private String tokenType = "Bearer"; // 令牌类型
}
package com.yd.common.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 用户信息实体类
*/
@Data
public class UserDetails implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String password;
private String nickname;
private String avatar;
private Integer status; // 1-启用,0-禁用
private List<String> roles; // 角色列表
private List<String> permissions; // 权限列表
}
package com.yd.common.exception;
import lombok.Getter;
/**
* 业务异常类
*/
@Getter
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private int code;
private String msg;
public BusinessException(String msg) {
super(msg);
this.code = 500;
this.msg = msg;
}
public BusinessException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
}
package com.yd.common.result;
import lombok.Data;
import java.io.Serializable;
/**
* 统一响应结果
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int code;
private String msg;
private T data;
private Result() {}
/**
* 成功返回
*/
public static <T> Result<T> success(T data) {
Result<T> result = new Result<T>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
/**
* 失败返回
*/
public static <T> Result<T> fail(int code, String msg) {
Result<T> result = new Result<T>();
result.setCode(code);
result.setMsg(msg);
return result;
}
/**
* 失败返回
*/
public static <T> Result<T> fail(String msg) {
return fail(500, msg);
}
}
#Generated by Maven
#Mon Jul 28 18:02:10 CST 2025
version=1.0-SNAPSHOT
groupId=com.yd
artifactId=yd-common
com\yd\common\dto\LoginDTO.class
com\yd\common\dto\TokenDTO.class
com\yd\common\constant\ServerNameConstants.class
com\yd\common\exception\BusinessException.class
com\yd\common\result\Result.class
com\yd\common\entity\UserDetails.class
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\entity\UserDetails.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\constant\ServerNameConstants.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\result\Result.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\dto\LoginDTO.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\exception\BusinessException.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-common\src\main\java\com\yd\common\dto\TokenDTO.java
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />
\ No newline at end of file
<?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>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yd-feign</artifactId>
<name>yd-feign</name>
<description>Feign组件模块</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package com.yd.feign.client;
import com.yd.common.entity.UserDetails;
import com.yd.common.result.Result;
import com.yd.feign.client.fallback.UserFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 用户服务Feign客户端
*/
@FeignClient(name = "yd-user-service", fallbackFactory = UserFeignFallbackFactory.class)
public interface UserFeignClient {
/**
* 根据用户名获取用户信息
*/
@GetMapping("/user/getByUsername")
Result<UserDetails> getByUsername(@RequestParam("username") String username);
}
package com.yd.feign.client.fallback;
import com.yd.common.entity.UserDetails;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.feign.client.UserFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 用户服务Feign降级处理
*/
@Slf4j
@Component
public class UserFeignFallbackFactory implements FallbackFactory<UserFeignClient> {
public UserFeignClient create(final Throwable cause) {
return new UserFeignClient() {
public Result<UserDetails> getByUsername(String username) {
log.error("调用用户服务失败: {}", cause.getMessage());
throw new BusinessException("获取用户信息失败,请稍后重试");
}
};
}
}
package com.yd.feign.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.RequestInterceptor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
/**
* Feign配置类,传递请求头
*/
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return template -> {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
// 传递所有请求头,防止部分丢失
template.header(name, value);
}
}
}
};
}
}
#Generated by Maven
#Mon Jul 28 18:02:38 CST 2025
version=1.0-SNAPSHOT
groupId=com.yd
artifactId=yd-feign
com\yd\feign\client\UserFeignClient.class
com\yd\feign\client\fallback\UserFeignFallbackFactory.class
com\yd\feign\client\fallback\UserFeignFallbackFactory$1.class
com\yd\feign\config\FeignConfig.class
D:\soft\ideaproject\v3\yd-cloud-core\yd-feign\src\main\java\com\yd\feign\client\fallback\UserFeignFallbackFactory.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-feign\src\main\java\com\yd\feign\config\FeignConfig.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-feign\src\main\java\com\yd\feign\client\UserFeignClient.java
<?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>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yd-framework</artifactId>
<name>yd-framework</name>
<description>框架配置模块</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package com.yd.framework.annotation;
import java.lang.annotation.*;
/**
* 权限注解,用于方法级别的权限控制
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequirePermission {
String value(); // 权限编码
}
package com.yd.framework.handler;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
public Result<?> handleBusinessException(BusinessException e) {
log.error("业务异常: {}", e.getMessage());
return Result.fail(e.getCode(), e.getMessage());
}
/**
* 处理参数校验异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
String message = fieldError != null ? fieldError.getDefaultMessage() : "参数校验失败";
log.error("参数校验异常: {}", message);
return Result.fail(400, message);
}
/**
* 处理其他异常
*/
@ExceptionHandler(Exception.class)
public Result<?> handleException(Exception e) {
log.error("系统异常: ", e);
return Result.fail("系统异常,请联系管理员");
}
}
#Generated by Maven
#Mon Jul 28 18:02:41 CST 2025
version=1.0-SNAPSHOT
groupId=com.yd
artifactId=yd-framework
com\yd\framework\annotation\RequirePermission.class
com\yd\framework\handler\GlobalExceptionHandler.class
D:\soft\ideaproject\v3\yd-cloud-core\yd-framework\src\main\java\com\yd\framework\handler\GlobalExceptionHandler.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-framework\src\main\java\com\yd\framework\annotation\RequirePermission.java
<?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>
<groupId>com.yd</groupId>
<artifactId>yd-cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yd-gateway</artifactId>
<name>yd-gateway</name>
<description>网关模块</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-auth-core</artifactId>
</dependency>
<dependency>
<groupId>com.yd</groupId>
<artifactId>yd-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
package com.yd.gateway;
import com.yd.common.constant.ServerNameConstants;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* 网关启动程序
*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableFeignClients(basePackages = "com.yd.gateway.**")
public class GatewayApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(GatewayApplication.class)
.properties("spring.config.name:bootstrap", "config/bootstrap.yml")
.properties("spring.application.name="+ ServerNameConstants.ydGateway)
.build().run(args);
System.out.println("(♥◠‿◠)ノ゙ yd-gateway网关启动成功 ლ(´ڡ`ლ)゙ ");
}
}
package com.yd.gateway.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 网关路由配置
*/
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 认证服务路由
.route("yd-auth-service", r -> r.path("/auth/**")
.uri("lb://yd-auth-service"))
// 用户服务路由
.route("yd-user-service", r -> r.path("/user/**")
.uri("lb://yd-user-service"))
// SCRM服务路由
.route("yd-scrm-service", r -> r.path("/scrm/**")
.uri("lb://yd-scrm-service"))
.build();
}
}
package com.yd.gateway.config;
import com.yd.gateway.filter.AuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
/**
* 网关安全配置
*/
@Configuration
@EnableWebFluxSecurity
public class GatewaySecurityConfig {
private final AuthenticationFilter authenticationFilter;
public GatewaySecurityConfig(AuthenticationFilter authenticationFilter) {
this.authenticationFilter = authenticationFilter;
}
@Bean
@Order(-1)
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.csrf().disable()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.authorizeExchange()
// 放行登录和刷新令牌接口
.pathMatchers("/auth/login", "/auth/refresh-token").permitAll()
// 放行健康检查接口
.pathMatchers("/actuator/health/**").permitAll()
// 其他请求需要认证
.anyExchange().authenticated()
.and()
.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.build();
}
}
package com.yd.gateway.filter;
import com.yd.auth.core.security.DummyAuthenticationManager;
import com.yd.auth.core.utils.JwtUtils;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import io.jsonwebtoken.Claims;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import com.alibaba.fastjson.JSON;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 网关认证过滤器
*/
@Component
public class AuthenticationFilter extends AuthenticationWebFilter {
private final JwtUtils jwtUtils;
public AuthenticationFilter(JwtUtils jwtUtils) {
super(new DummyAuthenticationManager());
this.jwtUtils = jwtUtils;
setServerAuthenticationConverter(jwtAuthenticationConverter());
}
/**
* JWT认证转换器
*/
private ServerAuthenticationConverter jwtAuthenticationConverter() {
return exchange -> {
ServerHttpRequest request = exchange.getRequest();
String token = getTokenFromRequest(request);
if (token == null) {
return Mono.error(new BusinessException("未提供令牌"));
}
try {
// 验证令牌
if (!jwtUtils.validateToken(token)) {
return Mono.error(new BusinessException("无效的令牌"));
}
// 解析令牌
Claims claims = jwtUtils.parseToken(token);
String username = claims.getSubject();
// 获取角色信息
List<String> roles = (List<String>) claims.get("roles");
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
if (roles != null && !roles.isEmpty()) {
authorities = roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
}
// 设置认证信息
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null, authorities);
return Mono.just(authentication);
} catch (Exception e) {
return Mono.error(new BusinessException(e.getMessage()));
}
};
}
/**
* 从请求头中获取令牌
*/
private String getTokenFromRequest(ServerHttpRequest request) {
String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
/**
* 处理认证失败
*/
protected Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
ServerWebExchange exchange = webFilterExchange.getExchange();
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
Result<?> result = Result.fail(401, exception.getMessage());
byte[] bytes = JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
return exchange.getResponse().writeWith(Mono.just(buffer));
}
}
#Generated by Maven
#Mon Jul 28 18:02:36 CST 2025
version=1.0-SNAPSHOT
groupId=com.yd
artifactId=yd-gateway
com\yd\gateway\config\GatewaySecurityConfig.class
com\yd\gateway\GatewayApplication.class
com\yd\gateway\config\GatewayConfig.class
com\yd\gateway\filter\AuthenticationFilter.class
D:\soft\ideaproject\v3\yd-cloud-core\yd-gateway\src\main\java\com\yd\gateway\config\GatewayConfig.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-gateway\src\main\java\com\yd\gateway\config\GatewaySecurityConfig.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-gateway\src\main\java\com\yd\gateway\GatewayApplication.java
D:\soft\ideaproject\v3\yd-cloud-core\yd-gateway\src\main\java\com\yd\gateway\filter\AuthenticationFilter.java
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment