Commit 3a50cebe77d39c2983ea811de39f462beeb43a64
1 parent
7f728d42
chore(backend): add CORS config and dev admin seed script
Enables the new frontend/ Vite app (localhost:5173) to call the backend across origins. Adds OPTIONS preflight permitAll. Seed script provisions an admin user (sUserName=admin / password=666666) for first-run login.
Showing
3 changed files
with
61 additions
and
0 deletions
backend/src/main/java/com/xly/erp/common/config/CorsConfig.java
0 → 100644
| 1 | +package com.xly.erp.common.config; | ||
| 2 | + | ||
| 3 | +import org.springframework.context.annotation.Bean; | ||
| 4 | +import org.springframework.context.annotation.Configuration; | ||
| 5 | +import org.springframework.web.cors.CorsConfiguration; | ||
| 6 | +import org.springframework.web.cors.CorsConfigurationSource; | ||
| 7 | +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +@Configuration | ||
| 12 | +public class CorsConfig { | ||
| 13 | + | ||
| 14 | + @Bean | ||
| 15 | + public CorsConfigurationSource corsConfigurationSource() { | ||
| 16 | + CorsConfiguration cfg = new CorsConfiguration(); | ||
| 17 | + cfg.setAllowedOrigins(List.of( | ||
| 18 | + "http://localhost:5173", | ||
| 19 | + "http://127.0.0.1:5173" | ||
| 20 | + )); | ||
| 21 | + cfg.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); | ||
| 22 | + cfg.setAllowedHeaders(List.of("*")); | ||
| 23 | + cfg.setExposedHeaders(List.of("Authorization")); | ||
| 24 | + cfg.setAllowCredentials(true); | ||
| 25 | + cfg.setMaxAge(3600L); | ||
| 26 | + | ||
| 27 | + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
| 28 | + source.registerCorsConfiguration("/api/**", cfg); | ||
| 29 | + return source; | ||
| 30 | + } | ||
| 31 | +} |
backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java
| @@ -4,6 +4,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat | @@ -4,6 +4,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat | ||
| 4 | import org.springframework.context.annotation.Bean; | 4 | import org.springframework.context.annotation.Bean; |
| 5 | import org.springframework.context.annotation.Configuration; | 5 | import org.springframework.context.annotation.Configuration; |
| 6 | import org.springframework.http.HttpMethod; | 6 | import org.springframework.http.HttpMethod; |
| 7 | +import org.springframework.security.config.Customizer; | ||
| 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; | 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| 8 | import org.springframework.security.config.http.SessionCreationPolicy; | 9 | import org.springframework.security.config.http.SessionCreationPolicy; |
| 9 | import org.springframework.security.web.SecurityFilterChain; | 10 | import org.springframework.security.web.SecurityFilterChain; |
| @@ -24,8 +25,10 @@ public class SecurityConfig { | @@ -24,8 +25,10 @@ public class SecurityConfig { | ||
| 24 | @Bean | 25 | @Bean |
| 25 | SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | 26 | SecurityFilterChain filterChain(HttpSecurity http) throws Exception { |
| 26 | http.csrf(csrf -> csrf.disable()) | 27 | http.csrf(csrf -> csrf.disable()) |
| 28 | + .cors(Customizer.withDefaults()) | ||
| 27 | .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | 29 | .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) |
| 28 | .authorizeHttpRequests(auth -> auth | 30 | .authorizeHttpRequests(auth -> auth |
| 31 | + .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() | ||
| 29 | .requestMatchers(HttpMethod.POST, "/api/usr/auth/login").permitAll() | 32 | .requestMatchers(HttpMethod.POST, "/api/usr/auth/login").permitAll() |
| 30 | .anyRequest().authenticated() | 33 | .anyRequest().authenticated() |
| 31 | ) | 34 | ) |
scripts/seed-dev-admin.sh
0 → 100755
| 1 | +#!/usr/bin/env bash | ||
| 2 | +# Seed a dev admin user (sUserName=admin, password=666666). | ||
| 3 | +# Run once after first `mvn spring-boot:run` so Flyway has applied V1. | ||
| 4 | +# Idempotent: uses INSERT IGNORE on the unique key. | ||
| 5 | + | ||
| 6 | +set -euo pipefail | ||
| 7 | + | ||
| 8 | +DB_HOST="${DB_HOST:-127.0.0.1}" | ||
| 9 | +DB_PORT="${DB_PORT:-3306}" | ||
| 10 | +DB_SCHEMA="${DB_SCHEMA:-xly_erp}" | ||
| 11 | +DB_USER="${DB_USER:-root}" | ||
| 12 | + | ||
| 13 | +# BCrypt(666666) cost 10. Spring's BCryptPasswordEncoder accepts both $2a$ and $2b$ prefixes. | ||
| 14 | +HASH='$2b$10$ZzbGP0yWo3QJkaiZqEgtAOQVrzrti911VqbY7FoethhGQFPV0/Oj6' | ||
| 15 | + | ||
| 16 | +mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" ${DB_PASSWORD:+-p"$DB_PASSWORD"} "$DB_SCHEMA" <<SQL | ||
| 17 | +INSERT IGNORE INTO tUser | ||
| 18 | + (sBrandsId, sSubsidiaryId, tCreateDate, | ||
| 19 | + sUserNo, sUserName, sUserType, sLanguage, bCanModifyDocs, | ||
| 20 | + sPasswordHash, sCreatedBy, bDeleted) | ||
| 21 | +VALUES | ||
| 22 | + ('XLY', 'XLY', NOW(), | ||
| 23 | + 'admin', 'admin', '超级管理员', 'zh', 1, | ||
| 24 | + '$HASH', 'system', 0); | ||
| 25 | +SQL | ||
| 26 | + | ||
| 27 | +echo "Seeded dev admin: sUserName=admin / password=666666" |