From 80806c35ce592478b63cdde23b34ee08eced08ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8D=95=E9=A3=8E=E7=9A=84=E9=80=8D=E9=81=A5=E4=BE=AF?= Date: Sat, 18 Oct 2025 17:00:32 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=B6=85=E8=BF=873MB=E7=9A=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=BC=9A=E5=88=9B=E5=BB=BA=E4=B8=B4=E6=97=B6=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E5=9B=A0=E4=B8=BA=E6=AF=8F=E6=AC=A1=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E7=9A=84=E6=96=87=E4=BB=B6=E9=83=BD=E6=98=AF1MB,?= =?UTF-8?q?=E6=89=80=E4=BB=A5=E7=9B=B4=E6=8E=A5=E5=86=85=E5=AD=98=E5=A4=84?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E4=B8=8D=E4=BC=9A=E5=88=9B=E5=BB=BA=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d68f304..4534069 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,8 +36,14 @@ logging: server: port: 8888 -# address: 0.0.0.0 # 这里不会影响局域网访问 - + # address: 0.0.0.0 # 这里不会影响局域网访问 + servlet: + multipart: + enabled: true + max-file-size: 3MB + max-request-size: 3MB + file-size-threshold: 0 # 所有文件先存内存,不写临时文件 +# location: /tmp/tomcat # 如需自定义临时目录 # JWT configuration jwt: accessExpiration: 7200000 # 2 hours in milliseconds -- Gitee From 4d5e83da359e14db3e5bfdb25c06522c70bb78b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8D=95=E9=A3=8E=E7=9A=84=E9=80=8D=E9=81=A5=E4=BE=AF?= Date: Sun, 19 Oct 2025 15:54:41 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=85=88=E6=81=A2=E5=A4=8D401=20=E3=80=82?= =?UTF-8?q?=20https://gitee.com/fly-rabbit/air-share/issues/ID2HZY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/SecurityConfig.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/hxy/dragon/config/security/SecurityConfig.java b/src/main/java/hxy/dragon/config/security/SecurityConfig.java index 9eff082..e5966f0 100644 --- a/src/main/java/hxy/dragon/config/security/SecurityConfig.java +++ b/src/main/java/hxy/dragon/config/security/SecurityConfig.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; @@ -14,14 +15,9 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.http.HttpMethod; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; /** * Security configuration @@ -60,14 +56,23 @@ public class SecurityConfig { @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return (request, response, authException) -> { + + // 获取 header? 决定302还是 401? + // For template pages (like /files), redirect to login - response.sendRedirect("/login"); +// response.sendRedirect("/login"); + + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":401,\"msg\":\"Unauthorized\"}"); }; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http + .formLogin(form -> form.disable()) // 禁用表单登录(避免 302) + .httpBasic(httpBasic -> httpBasic.disable()) // 如果不需要 Basic .csrf(AbstractHttpConfigurer::disable) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) .exceptionHandling(ex -> ex.authenticationEntryPoint(authenticationEntryPoint())) -- Gitee From 7f89e9724d6bc538d25b56b7396dfcefbbb75412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8D=95=E9=A3=8E=E7=9A=84=E9=80=8D=E9=81=A5=E4=BE=AF?= Date: Sun, 19 Oct 2025 16:01:58 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=BF=99=E9=87=8C=E5=B9=B6=E4=B8=8D?= =?UTF-8?q?=E5=A5=BD=E5=A4=84=E7=90=86=EF=BC=8C=E5=9B=A0=E4=B8=BA=E5=AF=B9?= =?UTF-8?q?=E4=BA=8E=E4=B8=8D=E5=90=8C=E5=BD=A2=E5=BC=8F=E7=9A=84=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=EF=BC=8C=E5=85=B6=E5=AE=9E=E6=8E=A5=E5=8F=A3=E9=83=BD?= =?UTF-8?q?=E6=98=AFjson=E6=A0=BC=E5=BC=8F=E6=95=B0=E6=8D=AE=EF=BC=8C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E4=B8=8D=E5=90=8C=E7=9A=84=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=EF=BC=8C=E5=8A=A0=E5=85=A5=E4=B8=8D=E5=90=8C=E7=9A=84header?= =?UTF-8?q?=E6=A0=87=E8=AE=B0=EF=BC=8C=E4=BB=A5=E5=B8=AE=E5=8A=A9=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=86=B3=E5=AE=9A=E6=98=AF401=E8=BF=98=E6=98=AF302.?= =?UTF-8?q?=20https://gitee.com/fly-rabbit/air-share/issues/ID2HZY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/SecurityConfig.java | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/src/main/java/hxy/dragon/config/security/SecurityConfig.java b/src/main/java/hxy/dragon/config/security/SecurityConfig.java index e5966f0..91db772 100644 --- a/src/main/java/hxy/dragon/config/security/SecurityConfig.java +++ b/src/main/java/hxy/dragon/config/security/SecurityConfig.java @@ -5,6 +5,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; @@ -17,7 +19,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; /** * Security configuration @@ -56,26 +60,61 @@ public class SecurityConfig { @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return (request, response, authException) -> { + if (isApiRequest((HttpServletRequest) request)) { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":401,\"msg\":\"Unauthorized\"}"); + } else { + response.sendRedirect("/login"); + } + }; + } - // 获取 header? 决定302还是 401? + private boolean isApiRequest(HttpServletRequest request) { + String uri = request.getRequestURI(); + String accept = request.getHeader("Accept"); + String contentType = request.getHeader("Content-Type"); + String xrw = request.getHeader("X-Requested-With"); + if (uri != null && uri.startsWith("/file/")) { + return true; + } + if (xrw != null && "XMLHttpRequest".equalsIgnoreCase(xrw)) { + return true; + } + if (accept != null && accept.toLowerCase().contains("application/json")) { + return true; + } + if (contentType != null && contentType.toLowerCase().contains("application/json")) { + return true; + } + return false; + } - // For template pages (like /files), redirect to login -// response.sendRedirect("/login"); + @Bean + public AuthenticationEntryPoint loginRedirectEntryPoint() { + return new LoginUrlAuthenticationEntryPoint("/login"); + } - response.setStatus(HttpStatus.UNAUTHORIZED.value()); + @Bean + public AccessDeniedHandler restAccessDeniedHandler() { + return (request, response, ex) -> { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.setContentType("application/json;charset=UTF-8"); - response.getWriter().write("{\"code\":401,\"msg\":\"Unauthorized\"}"); + response.getWriter().write("{\"code\":403,\"msg\":\"Forbidden\"}"); }; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http - .formLogin(form -> form.disable()) // 禁用表单登录(避免 302) - .httpBasic(httpBasic -> httpBasic.disable()) // 如果不需要 Basic + .formLogin(form -> form.disable()) + .httpBasic(httpBasic -> httpBasic.disable()) .csrf(AbstractHttpConfigurer::disable) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) - .exceptionHandling(ex -> ex.authenticationEntryPoint(authenticationEntryPoint())) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .exceptionHandling(ex -> ex + .authenticationEntryPoint(authenticationEntryPoint()) + .accessDeniedHandler(restAccessDeniedHandler()) + ) .authorizeHttpRequests(authz -> authz // Public endpoints .requestMatchers("/auth/**").permitAll() -- Gitee