Compare commits
2 Commits
5803080352
...
25eeab4940
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25eeab4940 | ||
|
|
f6d1d719a9 |
17984
logs/web_project.log
17984
logs/web_project.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
BIN
logs/web_project.log.2025-10-28.0.gz
Normal file
BIN
logs/web_project.log.2025-10-28.0.gz
Normal file
Binary file not shown.
BIN
logs/web_project.log.2025-10-29.0.gz
Normal file
BIN
logs/web_project.log.2025-10-29.0.gz
Normal file
Binary file not shown.
BIN
logs/web_project.log.2025-10-30.0.gz
Normal file
BIN
logs/web_project.log.2025-10-30.0.gz
Normal file
Binary file not shown.
BIN
logs/web_project.log.2025-10-31.0.gz
Normal file
BIN
logs/web_project.log.2025-10-31.0.gz
Normal file
Binary file not shown.
19
pom.xml
19
pom.xml
@@ -81,6 +81,13 @@
|
|||||||
<version>0.18.2</version>
|
<version>0.18.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JWT依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt</artifactId>
|
||||||
|
<version>0.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JCache API -->
|
<!-- JCache API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.cache</groupId>
|
<groupId>javax.cache</groupId>
|
||||||
@@ -138,6 +145,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>com.qf.myafterprojecy.MyAfterProjecyApplication</mainClass>
|
<mainClass>com.qf.myafterprojecy.MyAfterProjecyApplication</mainClass>
|
||||||
<skip>false</skip>
|
<skip>false</skip>
|
||||||
|
<jvmArguments>-Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8</jvmArguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -149,6 +157,17 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<!-- 确保项目编译和资源处理使用UTF-8编码 -->
|
||||||
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -3,11 +3,40 @@ package com.qf.myafterprojecy;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用主类
|
||||||
|
* 设置系统编码并启动Spring Boot应用
|
||||||
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class MyAfterProjecyApplication {
|
public class MyAfterProjecyApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
// 在应用启动前设置系统编码,确保所有输出都使用UTF-8
|
||||||
|
setSystemEncoding();
|
||||||
|
|
||||||
|
// 启动Spring Boot应用
|
||||||
SpringApplication.run(MyAfterProjecyApplication.class, args);
|
SpringApplication.run(MyAfterProjecyApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置系统编码为UTF-8
|
||||||
|
* 解决控制台输出和日志中的中文乱码问题
|
||||||
|
*/
|
||||||
|
private static void setSystemEncoding() {
|
||||||
|
// 设置系统属性,确保所有输出流都使用UTF-8编码
|
||||||
|
System.setProperty("file.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
System.setProperty("sun.stdout.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
System.setProperty("sun.stderr.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
|
||||||
|
// 设置默认字符编码
|
||||||
|
try {
|
||||||
|
java.nio.charset.Charset.defaultCharset();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 记录编码设置异常
|
||||||
|
System.err.println("设置默认字符编码时发生异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符编码配置类
|
||||||
|
* 确保所有HTTP请求和响应都使用UTF-8编码,解决中文乱码问题
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CharacterEncodingConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建字符编码过滤器
|
||||||
|
* 优先级设置为最高,确保在所有其他过滤器之前执行
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<Filter> characterEncodingFilter() {
|
||||||
|
// 创建字符编码过滤器
|
||||||
|
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
|
||||||
|
|
||||||
|
// 设置请求编码为UTF-8
|
||||||
|
encodingFilter.setEncoding(StandardCharsets.UTF_8.name());
|
||||||
|
|
||||||
|
// 强制请求使用UTF-8编码
|
||||||
|
encodingFilter.setForceRequestEncoding(true);
|
||||||
|
|
||||||
|
// 强制响应使用UTF-8编码
|
||||||
|
encodingFilter.setForceResponseEncoding(true);
|
||||||
|
|
||||||
|
// 创建过滤器注册Bean
|
||||||
|
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(encodingFilter);
|
||||||
|
|
||||||
|
// 设置过滤器顺序为最高优先级
|
||||||
|
registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||||
|
|
||||||
|
// 为所有请求路径注册过滤器
|
||||||
|
registrationBean.addUrlPatterns("/*");
|
||||||
|
|
||||||
|
return registrationBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.utils.JwtUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT认证过滤器,用于验证token并授权用户
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtils jwtUtils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Value("${jwt.header:Authorization}")
|
||||||
|
private String tokenHeader;
|
||||||
|
|
||||||
|
@Value("${jwt.token-prefix:Bearer}")
|
||||||
|
private String tokenPrefix;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
try {
|
||||||
|
// 获取token
|
||||||
|
String token = getTokenFromRequest(request);
|
||||||
|
System.out.println(token);
|
||||||
|
if (token != null && validateToken(token)) {
|
||||||
|
// 从token中获取用户名
|
||||||
|
String username = jwtUtils.getUsernameFromToken(token);
|
||||||
|
|
||||||
|
// 加载用户信息
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
|
||||||
|
// 创建认证对象
|
||||||
|
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
|
userDetails, null, userDetails.getAuthorities());
|
||||||
|
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
|
||||||
|
// 设置认证信息到上下文
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("无法设置用户认证: {}", e);
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从请求头中获取token
|
||||||
|
*/
|
||||||
|
private String getTokenFromRequest(HttpServletRequest request) {
|
||||||
|
String bearerToken = request.getHeader(tokenHeader);
|
||||||
|
if (bearerToken != null && bearerToken.startsWith(tokenPrefix + " ")) {
|
||||||
|
return bearerToken.substring(tokenPrefix.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
*/
|
||||||
|
private boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
String username = jwtUtils.getUsernameFromToken(token);
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
return jwtUtils.validateToken(token, userDetails);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("无效的token: {}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
|||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security配置类
|
* Spring Security配置类
|
||||||
@@ -31,6 +32,9 @@ public class SecurityConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置AuthenticationManager Bean
|
* 配置AuthenticationManager Bean
|
||||||
* 使用AuthenticationConfiguration来获取认证管理器,这是更现代的方式
|
* 使用AuthenticationConfiguration来获取认证管理器,这是更现代的方式
|
||||||
@@ -61,8 +65,10 @@ public class SecurityConfig {
|
|||||||
.antMatchers(HttpMethod.GET,"/api/markdowns/**").permitAll()
|
.antMatchers(HttpMethod.GET,"/api/markdowns/**").permitAll()
|
||||||
.antMatchers(HttpMethod.GET,"/api/articles/**").permitAll()
|
.antMatchers(HttpMethod.GET,"/api/articles/**").permitAll()
|
||||||
.antMatchers(HttpMethod.GET,"/api/messages/**").permitAll()
|
.antMatchers(HttpMethod.GET,"/api/messages/**").permitAll()
|
||||||
|
.antMatchers(HttpMethod.GET,"/api/categories/**").permitAll()
|
||||||
// 公开post请求
|
// 公开post请求
|
||||||
.antMatchers(HttpMethod.POST,"/api/messages/**").permitAll()
|
.antMatchers(HttpMethod.POST,"/api/messages/**").permitAll()
|
||||||
|
.antMatchers(HttpMethod.POST,"/api/users/**").permitAll()
|
||||||
// 管理员才能访问的路径
|
// 管理员才能访问的路径
|
||||||
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
||||||
// 其他所有请求都需要认证
|
// 其他所有请求都需要认证
|
||||||
@@ -72,6 +78,18 @@ public class SecurityConfig {
|
|||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||||
|
|
||||||
|
// 添加JWT认证过滤器
|
||||||
|
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
// 确保Spring Security不会添加额外的CharacterEncodingFilter
|
||||||
|
// 因为我们在CharacterEncodingConfig中已经配置了自定义的过滤器
|
||||||
|
http.addFilterBefore((request, response, chain) -> {
|
||||||
|
// 确保响应使用UTF-8编码
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}, JwtAuthenticationFilter.class);
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.config.ResponseMessage;
|
||||||
|
import com.qf.myafterprojecy.utils.JwtUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -31,6 +32,9 @@ public class AuthController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtils jwtUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录请求体
|
* 用户登录请求体
|
||||||
*/
|
*/
|
||||||
@@ -67,8 +71,7 @@ public class AuthController {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 创建认证令牌
|
// 创建认证令牌
|
||||||
UsernamePasswordAuthenticationToken authenticationToken =
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
|
||||||
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
|
|
||||||
|
|
||||||
// 执行认证
|
// 执行认证
|
||||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||||
@@ -78,12 +81,14 @@ public class AuthController {
|
|||||||
|
|
||||||
// 获取认证后的用户信息
|
// 获取认证后的用户信息
|
||||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||||
|
// 生成JWT token
|
||||||
|
String token = jwtUtils.generateToken(userDetails);
|
||||||
// 构建返回数据
|
// 构建返回数据
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
data.put("username", userDetails.getUsername());
|
data.put("username", userDetails.getUsername());
|
||||||
data.put("authorities", userDetails.getAuthorities());
|
data.put("authorities", userDetails.getAuthorities());
|
||||||
data.put("message", "登录成功");
|
data.put("token", token);
|
||||||
|
data.put("tokenPrefix", jwtUtils.getTokenPrefix());
|
||||||
|
|
||||||
return ResponseMessage.success(data, "登录成功");
|
return ResponseMessage.success(data, "登录成功");
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.qf.myafterprojecy.service.imp.ICategoryAttributeService;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ public class CategoryAttributeController {
|
|||||||
* @return 创建结果
|
* @return 创建结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category_attribute> createAttribute(@Valid @RequestBody CategoryAttributeDto dto) {
|
public ResponseMessage<Category_attribute> createAttribute(@Valid @RequestBody CategoryAttributeDto dto) {
|
||||||
log.info("接收创建分类属性的请求: 分类ID={}, 属性名称={}",
|
log.info("接收创建分类属性的请求: 分类ID={}, 属性名称={}",
|
||||||
dto.getCategoryid(), dto.getAttributename());
|
dto.getCategoryid(), dto.getAttributename());
|
||||||
@@ -66,6 +68,7 @@ public class CategoryAttributeController {
|
|||||||
* @return 更新结果
|
* @return 更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category_attribute> updateAttribute(
|
public ResponseMessage<Category_attribute> updateAttribute(
|
||||||
@PathVariable Integer id,
|
@PathVariable Integer id,
|
||||||
@Valid @RequestBody CategoryAttributeDto dto) {
|
@Valid @RequestBody CategoryAttributeDto dto) {
|
||||||
@@ -80,6 +83,7 @@ public class CategoryAttributeController {
|
|||||||
* @return 删除结果
|
* @return 删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteAttribute(@PathVariable Integer id) {
|
public ResponseMessage<Boolean> deleteAttribute(@PathVariable Integer id) {
|
||||||
log.info("接收删除分类属性的请求: ID={}", id);
|
log.info("接收删除分类属性的请求: ID={}", id);
|
||||||
return categoryAttributeService.deleteCategoryAttribute(id);
|
return categoryAttributeService.deleteCategoryAttribute(id);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.qf.myafterprojecy.service.imp.ICategoryService;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ public class CategoryController {
|
|||||||
* @return 返回创建结果
|
* @return 返回创建结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category> createCategory(@Valid @RequestBody CategoryDto categoryDto) {
|
public ResponseMessage<Category> createCategory(@Valid @RequestBody CategoryDto categoryDto) {
|
||||||
log.info("接收创建分类的请求: {}", categoryDto.getTypename());
|
log.info("接收创建分类的请求: {}", categoryDto.getTypename());
|
||||||
return categoryService.saveCategory(categoryDto);
|
return categoryService.saveCategory(categoryDto);
|
||||||
@@ -67,6 +69,7 @@ public class CategoryController {
|
|||||||
* @return 返回更新结果
|
* @return 返回更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category> updateCategory(
|
public ResponseMessage<Category> updateCategory(
|
||||||
@PathVariable Integer id,
|
@PathVariable Integer id,
|
||||||
@Valid @RequestBody CategoryDto categoryDto) {
|
@Valid @RequestBody CategoryDto categoryDto) {
|
||||||
@@ -80,6 +83,7 @@ public class CategoryController {
|
|||||||
* @return 返回删除结果
|
* @return 返回删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteCategory(@PathVariable Integer id) {
|
public ResponseMessage<Boolean> deleteCategory(@PathVariable Integer id) {
|
||||||
log.info("接收删除分类的请求: {}", id);
|
log.info("接收删除分类的请求: {}", id);
|
||||||
return categoryService.deleteCategory(id);
|
return categoryService.deleteCategory(id);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.qf.myafterprojecy.service.imp.IMessageService;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -87,6 +88,7 @@ public class MessageController {
|
|||||||
* 创建新消息
|
* 创建新消息
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
|
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
|
||||||
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
|
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
|
||||||
return messageService.saveMessage(message);
|
return messageService.saveMessage(message);
|
||||||
@@ -101,6 +103,7 @@ public class MessageController {
|
|||||||
* 根据ID删除消息
|
* 根据ID删除消息
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
|
||||||
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
|
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
|
||||||
logger.info("接收删除消息的请求: {}", id);
|
logger.info("接收删除消息的请求: {}", id);
|
||||||
return messageService.deleteMessage(id);
|
return messageService.deleteMessage(id);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import com.qf.myafterprojecy.service.imp.IUserService;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@@ -15,6 +17,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/users")
|
@RequestMapping("/api/users")
|
||||||
|
@Validated
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
|
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
|
||||||
@@ -38,6 +41,7 @@ public class UserController {
|
|||||||
* @return 用户列表
|
* @return 用户列表
|
||||||
*/
|
*/
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<List<Users>> getAllUsers() {
|
public ResponseMessage<List<Users>> getAllUsers() {
|
||||||
logger.info("获取所有用户列表");
|
logger.info("获取所有用户列表");
|
||||||
return userService.getAllUsers();
|
return userService.getAllUsers();
|
||||||
@@ -45,10 +49,10 @@ public class UserController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户名获取用户信息
|
* 根据用户名获取用户信息
|
||||||
* @param username 用户名
|
|
||||||
* @return 用户信息
|
* @return 用户信息
|
||||||
*/
|
*/
|
||||||
@GetMapping("/username/{username}")
|
@GetMapping("/username/{username}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
|
||||||
public ResponseMessage<Users> getUserByUsername(@PathVariable String username) {
|
public ResponseMessage<Users> getUserByUsername(@PathVariable String username) {
|
||||||
logger.info("根据用户名获取用户信息,用户名: {}", username);
|
logger.info("根据用户名获取用户信息,用户名: {}", username);
|
||||||
return userService.getUserByUsername(username);
|
return userService.getUserByUsername(username);
|
||||||
@@ -72,6 +76,7 @@ public class UserController {
|
|||||||
* @return 更新结果
|
* @return 更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
|
||||||
public ResponseMessage<Users> updateUser(@PathVariable Long id, @Valid @RequestBody UserDto userDto) {
|
public ResponseMessage<Users> updateUser(@PathVariable Long id, @Valid @RequestBody UserDto userDto) {
|
||||||
logger.info("更新用户信息,用户ID: {}", id);
|
logger.info("更新用户信息,用户ID: {}", id);
|
||||||
return userService.updateUser(id, userDto);
|
return userService.updateUser(id, userDto);
|
||||||
@@ -83,6 +88,7 @@ public class UserController {
|
|||||||
* @return 删除结果
|
* @return 删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteUser(@PathVariable Long id) {
|
public ResponseMessage<Boolean> deleteUser(@PathVariable Long id) {
|
||||||
logger.info("删除用户,用户ID: {}", id);
|
logger.info("删除用户,用户ID: {}", id);
|
||||||
return userService.deleteUser(id);
|
return userService.deleteUser(id);
|
||||||
@@ -94,6 +100,7 @@ public class UserController {
|
|||||||
* @return 用户列表
|
* @return 用户列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/role/{role}")
|
@GetMapping("/role/{role}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<List<Users>> getUsersByRole(@PathVariable int role) {
|
public ResponseMessage<List<Users>> getUsersByRole(@PathVariable int role) {
|
||||||
logger.info("根据角色查询用户列表,角色: {}", role);
|
logger.info("根据角色查询用户列表,角色: {}", role);
|
||||||
return userService.getUsersByRole(role);
|
return userService.getUsersByRole(role);
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class ArticleDto {
|
public class ArticleDto {
|
||||||
private Integer id;
|
private Integer articleid;
|
||||||
|
|
||||||
@NotBlank(message = "标题不能为空")
|
@NotBlank(message = "标题不能为空")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@NotBlank(message = "内容不能为空")
|
private String content;// 如果为空说明是长篇文章 不为空则是短篇说说
|
||||||
private String content;
|
|
||||||
|
|
||||||
@NotNull(message = "属性ID不能为空")
|
@NotNull(message = "属性ID不能为空")
|
||||||
private Integer attributeid;
|
private Integer attributeid;
|
||||||
|
|
||||||
private String img;
|
private String img;
|
||||||
|
|
||||||
|
private Integer viewCount;
|
||||||
|
|
||||||
|
private Integer likes;
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
// Getters and Setters
|
private String markdownscontent; // 文章内容的Markdown格式
|
||||||
|
|
||||||
public Integer getId() {
|
// Getters and Setters
|
||||||
return id;
|
public Integer getArticleid() {
|
||||||
|
return articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Integer id) {
|
public void setArticleid(Integer articleid) {
|
||||||
this.id = id;
|
this.articleid = articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
@@ -48,12 +49,12 @@ public class ArticleDto {
|
|||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getStatus() {
|
public Integer getAttributeid() {
|
||||||
return status;
|
return attributeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(Integer status) {
|
public void setAttributeid(Integer attributeid) {
|
||||||
this.status = status;
|
this.attributeid = attributeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImg() {
|
public String getImg() {
|
||||||
@@ -63,4 +64,36 @@ public class ArticleDto {
|
|||||||
public void setImg(String img) {
|
public void setImg(String img) {
|
||||||
this.img = img;
|
this.img = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getViewCount() {
|
||||||
|
return viewCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewCount(Integer viewCount) {
|
||||||
|
this.viewCount = viewCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikes(Integer likes) {
|
||||||
|
this.likes = likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMarkdownscontent() {
|
||||||
|
return markdownscontent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarkdownscontent(String markdownscontent) {
|
||||||
|
this.markdownscontent = markdownscontent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import javax.validation.constraints.NotBlank;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class CategoryAttributeDto {
|
public class CategoryAttributeDto {
|
||||||
|
private Integer attributeid;
|
||||||
|
|
||||||
@NotNull(message = "分类ID不能为空")
|
@NotNull(message = "分类ID不能为空")
|
||||||
private Integer categoryid;
|
private Integer categoryid;
|
||||||
@@ -12,6 +13,14 @@ public class CategoryAttributeDto {
|
|||||||
private String attributename;
|
private String attributename;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
|
public Integer getAttributeid() {
|
||||||
|
return attributeid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributeid(Integer attributeid) {
|
||||||
|
this.attributeid = attributeid;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getCategoryid() {
|
public Integer getCategoryid() {
|
||||||
return categoryid;
|
return categoryid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class CategoryDto {
|
public class CategoryDto {
|
||||||
private Integer typeid;
|
private Integer typeid;
|
||||||
|
|
||||||
|
@NotBlank(message = "分类名称不能为空")
|
||||||
private String typename;
|
private String typename;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class MarkdownDto {
|
|
||||||
@NotBlank(message = "Markdown内容不能为空")
|
|
||||||
private String markdownscontent;
|
|
||||||
|
|
||||||
public String getMarkdownscontent() {
|
|
||||||
return markdownscontent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMarkdownscontent(String markdownscontent) {
|
|
||||||
this.markdownscontent = markdownscontent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,8 @@ public class MessageDto {
|
|||||||
private Integer replyid;
|
private Integer replyid;
|
||||||
|
|
||||||
private Integer articleid;
|
private Integer articleid;
|
||||||
|
|
||||||
|
private Integer likes;
|
||||||
|
|
||||||
public Integer getReplyid() {
|
public Integer getReplyid() {
|
||||||
return replyid;
|
return replyid;
|
||||||
@@ -26,6 +28,7 @@ public class MessageDto {
|
|||||||
public void setReplyid(Integer replyid) {
|
public void setReplyid(Integer replyid) {
|
||||||
this.replyid = replyid;
|
this.replyid = replyid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getMessageid() {
|
public Integer getMessageid() {
|
||||||
return messageid;
|
return messageid;
|
||||||
}
|
}
|
||||||
@@ -81,4 +84,12 @@ public class MessageDto {
|
|||||||
public void setArticleid(Integer articleid) {
|
public void setArticleid(Integer articleid) {
|
||||||
this.articleid = articleid;
|
this.articleid = articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikes(Integer likes) {
|
||||||
|
this.likes = likes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.qf.myafterprojecy.pojo.dto;
|
|||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
public class UserDto {
|
public class UserDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
@NotBlank(message = "用户名不能为空")
|
@NotBlank(message = "用户名不能为空")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@@ -15,9 +17,16 @@ public class UserDto {
|
|||||||
@NotBlank(message = "手机号不能为空")
|
@NotBlank(message = "手机号不能为空")
|
||||||
private String phone;
|
private String phone;
|
||||||
|
|
||||||
@NotBlank(message = "角色不能为空")
|
|
||||||
private int role;
|
private int role;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
@@ -57,5 +66,4 @@ public class UserDto {
|
|||||||
public void setRole(int role) {
|
public void setRole(int role) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,10 @@ public class UserService implements IUserService {
|
|||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
BeanUtils.copyProperties(userDto, user);
|
BeanUtils.copyProperties(userDto, user);
|
||||||
|
|
||||||
// 保存更新后的用户
|
// 如果提供了新密码,则进行加密
|
||||||
|
if (userDto.getPassword() != null && !userDto.getPassword().isEmpty()) {
|
||||||
|
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||||
|
}
|
||||||
Users updatedUser = usersRepository.save(user);
|
Users updatedUser = usersRepository.save(user);
|
||||||
return ResponseMessage.update(true, updatedUser);
|
return ResponseMessage.update(true, updatedUser);
|
||||||
} catch (DataAccessException e) {
|
} catch (DataAccessException e) {
|
||||||
|
|||||||
103
src/main/java/com/qf/myafterprojecy/utils/JwtUtils.java
Normal file
103
src/main/java/com/qf/myafterprojecy/utils/JwtUtils.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.qf.myafterprojecy.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT工具类,用于生成和验证token
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtUtils {
|
||||||
|
|
||||||
|
@Value("${jwt.secret:default_secret_key_for_development}")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Value("${jwt.expiration:86400000}")
|
||||||
|
private long expiration;
|
||||||
|
|
||||||
|
@Value("${jwt.token-prefix:Bearer}")
|
||||||
|
private String tokenPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取用户名
|
||||||
|
*/
|
||||||
|
public String getUsernameFromToken(String token) {
|
||||||
|
return getClaimFromToken(token, Claims::getSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取过期时间
|
||||||
|
*/
|
||||||
|
public Date getExpirationDateFromToken(String token) {
|
||||||
|
return getClaimFromToken(token, Claims::getExpiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取指定的claim
|
||||||
|
*/
|
||||||
|
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||||
|
final Claims claims = getAllClaimsFromToken(token);
|
||||||
|
return claimsResolver.apply(claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token中的所有claims
|
||||||
|
*/
|
||||||
|
private Claims getAllClaimsFromToken(String token) {
|
||||||
|
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查token是否过期
|
||||||
|
*/
|
||||||
|
private Boolean isTokenExpired(String token) {
|
||||||
|
final Date expiration = getExpirationDateFromToken(token);
|
||||||
|
return expiration.before(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token
|
||||||
|
*/
|
||||||
|
public String generateToken(UserDetails userDetails) {
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
claims.put("authorities", userDetails.getAuthorities());
|
||||||
|
return doGenerateToken(claims, userDetails.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token的核心方法
|
||||||
|
*/
|
||||||
|
private String doGenerateToken(Map<String, Object> claims, String subject) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.setClaims(claims)
|
||||||
|
.setSubject(subject)
|
||||||
|
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||||
|
.setExpiration(new Date(System.currentTimeMillis() + expiration))
|
||||||
|
.signWith(SignatureAlgorithm.HS512, secret)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
*/
|
||||||
|
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||||
|
final String username = getUsernameFromToken(token);
|
||||||
|
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token前缀
|
||||||
|
*/
|
||||||
|
public String getTokenPrefix() {
|
||||||
|
return tokenPrefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,17 +61,21 @@ logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
|||||||
# 日志文件配置
|
# 日志文件配置
|
||||||
logging.file.name=logs/web_project.log
|
logging.file.name=logs/web_project.log
|
||||||
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
# 确保控制台输出使用UTF-8编码
|
||||||
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
# 日志编码配置 - 强制使用UTF-8
|
||||||
|
logging.charset.file=UTF-8
|
||||||
|
logging.charset.console=UTF-8
|
||||||
# Actuator配置 - 生产环境建议限制暴露的端点
|
# Actuator配置 - 生产环境建议限制暴露的端点
|
||||||
management.endpoints.web.exposure.include=health,info,metrics,prometheus
|
management.endpoints.web.exposure.include=health,info,metrics,prometheus
|
||||||
management.endpoint.health.show-details=when_authorized
|
management.endpoint.health.show-details=when_authorized
|
||||||
management.metrics.export.prometheus.enabled=true
|
management.metrics.export.prometheus.enabled=true
|
||||||
|
|
||||||
# JWT配置 - 生产环境应使用更安全的密钥和环境变量
|
# JWT配置 - 生产环境应使用更安全的密钥和环境变量
|
||||||
jwt.secret=mySecretKey
|
jwt.secret=myAfterProjectSecretKey2024SecureJwtTokenGeneration
|
||||||
jwt.expiration=86400000
|
jwt.expiration=86400000
|
||||||
jwt.header=Authorization
|
jwt.header=Authorization
|
||||||
jwt.token-prefix=Bearer
|
jwt.token-prefix=Bearer
|
||||||
|
|
||||||
# CORS配置 - 生产环境应限制允许的源
|
# CORS配置 - 生产环境应限制允许的源
|
||||||
cors.allowed-origins=http://localhost:3000
|
cors.allowed-origins=http://localhost:3000
|
||||||
@@ -85,20 +89,41 @@ security.basic.enabled=false
|
|||||||
security.ignored=/css/**,/js/**,/images/**,/favicon.ico
|
security.ignored=/css/**,/js/**,/images/**,/favicon.ico
|
||||||
|
|
||||||
# 生产环境建议配置
|
# 生产环境建议配置
|
||||||
# server.ssl.key-store=classpath:keystore.p12
|
|
||||||
# server.ssl.key-store-password=password
|
|
||||||
# server.ssl.key-store-type=PKCS12
|
|
||||||
# server.ssl.key-alias=tomcat
|
|
||||||
|
|
||||||
# 会话配置
|
# 会话配置
|
||||||
server.servlet.session.timeout=30m
|
server.servlet.session.timeout=30m
|
||||||
server.session.tracking-modes=cookie
|
server.session.tracking-modes=cookie
|
||||||
|
|
||||||
# 国际化配置
|
# 国际化配置
|
||||||
spring.mvc.locale-resolver=fixed
|
|
||||||
spring.web.locale=zh_CN
|
spring.web.locale=zh_CN
|
||||||
#
|
spring.messages.encoding=UTF-8
|
||||||
## 响应编码配置
|
# 响应编码配置 - 确保所有响应使用UTF-8编码
|
||||||
spring.http.encoding.charset=UTF-8
|
server.servlet.encoding.charset=UTF-8
|
||||||
spring.http.encoding.enabled=true
|
server.servlet.encoding.force=true
|
||||||
spring.http.encoding.force=true
|
server.servlet.encoding.force-request=true
|
||||||
|
server.servlet.encoding.force-response=true
|
||||||
|
server.servlet.encoding.enabled=true
|
||||||
|
|
||||||
|
# 配置控制台输出编码 - 通过日志系统配置确保中文显示正常
|
||||||
|
# logging.pattern.console=%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40logger{39}}{cyan} %clr{:}{faint} %m%n%wEx
|
||||||
|
|
||||||
|
# 配置Maven启动JVM参数(需在启动时通过命令行指定或在pom.xml中配置)
|
||||||
|
# 实际使用时请在启动命令中添加:-Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
|
||||||
|
|
||||||
|
# 更详细的日志配置 - 确保所有日志输出正确编码
|
||||||
|
# logging.level.root=INFO
|
||||||
|
# logging.level.org.springframework.web=DEBUG
|
||||||
|
# logging.level.org.springframework.security=INFO
|
||||||
|
# logging.level.com.qf.myafterprojecy=DEBUG
|
||||||
|
|
||||||
|
# 确保数据库连接编码正确
|
||||||
|
spring.datasource.hikari.data-source-properties.useUnicode=true
|
||||||
|
spring.datasource.hikari.data-source-properties.serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.hikari.data-source-properties.characterEncoding=utf-8
|
||||||
|
|
||||||
|
# 应用性能优化配置
|
||||||
|
spring.main.allow-bean-definition-overriding=true
|
||||||
|
spring.main.lazy-initialization=false
|
||||||
|
|
||||||
|
# API 文档配置
|
||||||
|
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
|
||||||
|
|||||||
Reference in New Issue
Block a user