first commit

This commit is contained in:
zyh
2025-08-24 15:33:03 +08:00
commit be437a360d
54 changed files with 1273 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
package com.gameplatform.server.security;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Map;
@Component
public class JwtService {
private final SecretKey key;
private final long accessTokenMinutes;
public JwtService(@Value("${security.jwt.secret}") String secret,
@Value("${security.jwt.access-token-minutes:30}") long accessTokenMinutes) {
// accept raw text secret; if base64 provided, still works with Decoders
byte[] bytes = secret.length() < 32 ? (secret + "_pad_to_32_chars_secret_key_value").getBytes() : secret.getBytes();
this.key = Keys.hmacShaKeyFor(bytes);
this.accessTokenMinutes = accessTokenMinutes;
}
public String generateToken(String subject, String userType, Long userId, String username, Map<String, Object> extra) {
Instant now = Instant.now();
var builder = Jwts.builder()
.setSubject(subject)
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(now.plus(accessTokenMinutes, ChronoUnit.MINUTES)))
.claim("userType", userType)
.claim("userId", userId)
.claim("username", username);
if (extra != null) {
extra.forEach(builder::claim);
}
return builder.signWith(key, SignatureAlgorithm.HS256).compact();
}
public io.jsonwebtoken.Claims parse(String token) {
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
}
}

View File

@@ -0,0 +1,37 @@
package com.gameplatform.server.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
return http
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.cors(ServerHttpSecurity.CorsSpec::disable)
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
.formLogin(ServerHttpSecurity.FormLoginSpec::disable)
.authorizeExchange(ex -> ex
.pathMatchers("/actuator/**").permitAll()
.pathMatchers(HttpMethod.POST, "/api/auth/login").permitAll()
.pathMatchers(HttpMethod.GET, "/api/auth/me").permitAll()
.anyExchange().permitAll() // 其他接口后续再收紧
)
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}