init
This commit is contained in:
38
backend/common/common-security/pom.xml
Normal file
38
backend/common/common-security/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-security</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "auth")
|
||||
public class AuthProperties {
|
||||
private boolean enabled = true;
|
||||
private boolean gatewayMode = false;
|
||||
private String tokenHeader = "Authorization";
|
||||
private String tokenPrefix = "Bearer ";
|
||||
private String secret = "k12study-dev-secret-k12study-dev-secret";
|
||||
private Duration accessTokenTtl = Duration.ofHours(12);
|
||||
private Duration refreshTokenTtl = Duration.ofDays(7);
|
||||
private List<String> whitelist = new ArrayList<>(List.of("/actuator/**", "/auth/login", "/auth/refresh"));
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isGatewayMode() {
|
||||
return gatewayMode;
|
||||
}
|
||||
|
||||
public void setGatewayMode(boolean gatewayMode) {
|
||||
this.gatewayMode = gatewayMode;
|
||||
}
|
||||
|
||||
public String getTokenHeader() {
|
||||
return tokenHeader;
|
||||
}
|
||||
|
||||
public void setTokenHeader(String tokenHeader) {
|
||||
this.tokenHeader = tokenHeader;
|
||||
}
|
||||
|
||||
public String getTokenPrefix() {
|
||||
return tokenPrefix;
|
||||
}
|
||||
|
||||
public void setTokenPrefix(String tokenPrefix) {
|
||||
this.tokenPrefix = tokenPrefix;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public Duration getAccessTokenTtl() {
|
||||
return accessTokenTtl;
|
||||
}
|
||||
|
||||
public void setAccessTokenTtl(Duration accessTokenTtl) {
|
||||
this.accessTokenTtl = accessTokenTtl;
|
||||
}
|
||||
|
||||
public Duration getRefreshTokenTtl() {
|
||||
return refreshTokenTtl;
|
||||
}
|
||||
|
||||
public void setRefreshTokenTtl(Duration refreshTokenTtl) {
|
||||
this.refreshTokenTtl = refreshTokenTtl;
|
||||
}
|
||||
|
||||
public List<String> getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
public void setWhitelist(List<String> whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import com.k12study.common.security.jwt.JwtTokenProvider;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AuthProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public JwtTokenProvider jwtTokenProvider(AuthProperties authProperties) {
|
||||
return new JwtTokenProvider(authProperties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public record RequestUserContext(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public final class RequestUserContextHolder {
|
||||
private static final ThreadLocal<RequestUserContext> CONTEXT = new ThreadLocal<>();
|
||||
|
||||
private RequestUserContextHolder() {
|
||||
}
|
||||
|
||||
public static void set(RequestUserContext context) {
|
||||
CONTEXT.set(context);
|
||||
}
|
||||
|
||||
public static RequestUserContext get() {
|
||||
return CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
import com.k12study.common.security.config.AuthProperties;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class JwtTokenProvider {
|
||||
private final AuthProperties authProperties;
|
||||
private final SecretKey secretKey;
|
||||
|
||||
public JwtTokenProvider(AuthProperties authProperties) {
|
||||
this.authProperties = authProperties;
|
||||
this.secretKey = Keys.hmacShaKeyFor(authProperties.getSecret().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String createAccessToken(JwtUserPrincipal principal) {
|
||||
Instant now = Instant.now();
|
||||
return Jwts.builder()
|
||||
.subject(principal.userId())
|
||||
.claim("username", principal.username())
|
||||
.claim("displayName", principal.displayName())
|
||||
.claim("tenantId", principal.tenantId())
|
||||
.claim("deptId", principal.deptId())
|
||||
.issuedAt(Date.from(now))
|
||||
.expiration(Date.from(now.plus(authProperties.getAccessTokenTtl())))
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public JwtUserPrincipal parse(String token) {
|
||||
Claims claims = Jwts.parser()
|
||||
.verifyWith(secretKey)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
return new JwtUserPrincipal(
|
||||
claims.getSubject(),
|
||||
claims.get("username", String.class),
|
||||
claims.get("displayName", String.class),
|
||||
claims.get("tenantId", String.class),
|
||||
claims.get("deptId", String.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
public record JwtUserPrincipal(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
Reference in New Issue
Block a user