Merge pull request 'kmbin92_2025081101' (#1) from kmbin92_2025081101 into main
Reviewed-on: https://demo.stam.kr/leejisun9/bio_backend/pulls/1
This commit is contained in:
56
README.md
56
README.md
@@ -1,2 +1,56 @@
|
||||
# bio_backend
|
||||
# Bio Backend
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- **Framework**: Spring Boot
|
||||
- **Database**: PostgreSQL
|
||||
- **ORM**: Spring Data JPA + QueryDSL
|
||||
- **Security**: Spring Security + JWT
|
||||
- **Build Tool**: Gradle
|
||||
- **Container**: Docker + Kubernetes
|
||||
|
||||
## 개발 가이드
|
||||
|
||||
### 1. 프로젝트 구조
|
||||
|
||||
```
|
||||
src/main/java/com/bio/bio_backend/
|
||||
├── domain/ # 도메인별 패키지
|
||||
│ └── user/
|
||||
│ └── member/ # 회원 도메인
|
||||
│ ├── controller/ # API 엔드포인트
|
||||
│ ├── service/ # 비즈니스 로직
|
||||
│ ├── repository/ # 데이터 접근
|
||||
│ ├── entity/ # JPA 엔티티
|
||||
│ └── dto/ # 데이터 전송 객체
|
||||
├── global/ # 공통 설정
|
||||
│ ├── config/ # 설정 클래스
|
||||
│ ├── security/ # 보안 설정
|
||||
│ ├── exception/ # 예외 처리
|
||||
│ └── utils/ # 유틸리티
|
||||
└── BioBackendApplication.java
|
||||
```
|
||||
|
||||
### 2. 트랜잭션 관리
|
||||
|
||||
#### 기본 설정
|
||||
|
||||
```java
|
||||
@Service
|
||||
@Transactional(readOnly = true) // 클래스 레벨: 읽기 전용 기본값
|
||||
public class MemberServiceImpl {
|
||||
|
||||
// 읽기 전용 메서드 (별도 어노테이션 불필요)
|
||||
public MemberDto selectMember(long seq) { ... }
|
||||
|
||||
// 쓰기 작업 메서드 (개별 @Transactional 적용)
|
||||
@Transactional
|
||||
public MemberDto createMember(MemberDto dto) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
#### 핵심 규칙
|
||||
|
||||
- **클래스 레벨**: `@Transactional(readOnly = true)` 기본 설정
|
||||
- **메서드별**: 데이터 수정 시에만 `@Transactional` 개별 적용
|
||||
- **설정**: `spring.jpa.open-in-view=false` (성능 최적화)
|
||||
|
39
build.gradle
39
build.gradle
@@ -24,19 +24,54 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 개발용 의존성 추가
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
// PostgreSQL JDBC 드라이버
|
||||
// PostgreSQL JDBC
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
|
||||
// Spring Securit
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
|
||||
// Validation
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
|
||||
// MapStruct
|
||||
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
|
||||
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
|
||||
|
||||
// MyBatis
|
||||
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
|
||||
|
||||
// jwt
|
||||
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
|
||||
|
||||
// lombok
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
|
||||
// querydsl
|
||||
implementation 'io.github.openfeign.querydsl:querydsl-jpa:6.11'
|
||||
annotationProcessor 'io.github.openfeign.querydsl:querydsl-apt:6.11:jpa'
|
||||
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
|
||||
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
|
||||
|
||||
// p6spy
|
||||
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// querydsl
|
||||
def generatedSrcDir = 'build/generated/sources/annotation-processor'
|
||||
clean {
|
||||
delete file(generatedSrcDir)
|
||||
}
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.generatedSourceOutputDirectory = file(generatedSrcDir)
|
||||
}
|
18
ddl/schema.sql
Normal file
18
ddl/schema.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
create table st_member (
|
||||
use_flag boolean not null,
|
||||
created_at timestamp(6) not null,
|
||||
created_oid bigint,
|
||||
last_login_at timestamp(6),
|
||||
oid bigint not null,
|
||||
updated_at timestamp(6) not null,
|
||||
updated_oid bigint,
|
||||
role varchar(40) not null check (role in ('MEMBER','ADMIN','USER','SYSTEM_ADMIN')),
|
||||
password varchar(100) not null,
|
||||
user_id varchar(100) not null,
|
||||
refresh_token varchar(200),
|
||||
primary key (oid)
|
||||
);
|
||||
|
||||
create index idx_member_user_id
|
||||
on st_member (user_id);
|
26
nginx-1.28.0/conf/fastcgi.conf
Normal file
26
nginx-1.28.0/conf/fastcgi.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
|
||||
# PHP only, required if PHP was built with --enable-force-cgi-redirect
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
25
nginx-1.28.0/conf/fastcgi_params
Normal file
25
nginx-1.28.0/conf/fastcgi_params
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
|
||||
# PHP only, required if PHP was built with --enable-force-cgi-redirect
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
109
nginx-1.28.0/conf/koi-utf
Normal file
109
nginx-1.28.0/conf/koi-utf
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
# This map is not a full koi8-r <> utf8 map: it does not contain
|
||||
# box-drawing and some other characters. Besides this map contains
|
||||
# several koi8-u and Byelorussian letters which are not in koi8-r.
|
||||
# If you need a full and standard map, use contrib/unicode2nginx/koi-utf
|
||||
# map instead.
|
||||
|
||||
charset_map koi8-r utf-8 {
|
||||
|
||||
80 E282AC ; # euro
|
||||
|
||||
95 E280A2 ; # bullet
|
||||
|
||||
9A C2A0 ; #
|
||||
|
||||
9E C2B7 ; # ·
|
||||
|
||||
A3 D191 ; # small yo
|
||||
A4 D194 ; # small Ukrainian ye
|
||||
|
||||
A6 D196 ; # small Ukrainian i
|
||||
A7 D197 ; # small Ukrainian yi
|
||||
|
||||
AD D291 ; # small Ukrainian soft g
|
||||
AE D19E ; # small Byelorussian short u
|
||||
|
||||
B0 C2B0 ; # °
|
||||
|
||||
B3 D081 ; # capital YO
|
||||
B4 D084 ; # capital Ukrainian YE
|
||||
|
||||
B6 D086 ; # capital Ukrainian I
|
||||
B7 D087 ; # capital Ukrainian YI
|
||||
|
||||
B9 E28496 ; # numero sign
|
||||
|
||||
BD D290 ; # capital Ukrainian soft G
|
||||
BE D18E ; # capital Byelorussian short U
|
||||
|
||||
BF C2A9 ; # (C)
|
||||
|
||||
C0 D18E ; # small yu
|
||||
C1 D0B0 ; # small a
|
||||
C2 D0B1 ; # small b
|
||||
C3 D186 ; # small ts
|
||||
C4 D0B4 ; # small d
|
||||
C5 D0B5 ; # small ye
|
||||
C6 D184 ; # small f
|
||||
C7 D0B3 ; # small g
|
||||
C8 D185 ; # small kh
|
||||
C9 D0B8 ; # small i
|
||||
CA D0B9 ; # small j
|
||||
CB D0BA ; # small k
|
||||
CC D0BB ; # small l
|
||||
CD D0BC ; # small m
|
||||
CE D0BD ; # small n
|
||||
CF D0BE ; # small o
|
||||
|
||||
D0 D0BF ; # small p
|
||||
D1 D18F ; # small ya
|
||||
D2 D180 ; # small r
|
||||
D3 D181 ; # small s
|
||||
D4 D182 ; # small t
|
||||
D5 D183 ; # small u
|
||||
D6 D0B6 ; # small zh
|
||||
D7 D0B2 ; # small v
|
||||
D8 D18C ; # small soft sign
|
||||
D9 D18B ; # small y
|
||||
DA D0B7 ; # small z
|
||||
DB D188 ; # small sh
|
||||
DC D18D ; # small e
|
||||
DD D189 ; # small shch
|
||||
DE D187 ; # small ch
|
||||
DF D18A ; # small hard sign
|
||||
|
||||
E0 D0AE ; # capital YU
|
||||
E1 D090 ; # capital A
|
||||
E2 D091 ; # capital B
|
||||
E3 D0A6 ; # capital TS
|
||||
E4 D094 ; # capital D
|
||||
E5 D095 ; # capital YE
|
||||
E6 D0A4 ; # capital F
|
||||
E7 D093 ; # capital G
|
||||
E8 D0A5 ; # capital KH
|
||||
E9 D098 ; # capital I
|
||||
EA D099 ; # capital J
|
||||
EB D09A ; # capital K
|
||||
EC D09B ; # capital L
|
||||
ED D09C ; # capital M
|
||||
EE D09D ; # capital N
|
||||
EF D09E ; # capital O
|
||||
|
||||
F0 D09F ; # capital P
|
||||
F1 D0AF ; # capital YA
|
||||
F2 D0A0 ; # capital R
|
||||
F3 D0A1 ; # capital S
|
||||
F4 D0A2 ; # capital T
|
||||
F5 D0A3 ; # capital U
|
||||
F6 D096 ; # capital ZH
|
||||
F7 D092 ; # capital V
|
||||
F8 D0AC ; # capital soft sign
|
||||
F9 D0AB ; # capital Y
|
||||
FA D097 ; # capital Z
|
||||
FB D0A8 ; # capital SH
|
||||
FC D0AD ; # capital E
|
||||
FD D0A9 ; # capital SHCH
|
||||
FE D0A7 ; # capital CH
|
||||
FF D0AA ; # capital hard sign
|
||||
}
|
103
nginx-1.28.0/conf/koi-win
Normal file
103
nginx-1.28.0/conf/koi-win
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
charset_map koi8-r windows-1251 {
|
||||
|
||||
80 88 ; # euro
|
||||
|
||||
95 95 ; # bullet
|
||||
|
||||
9A A0 ; #
|
||||
|
||||
9E B7 ; # ·
|
||||
|
||||
A3 B8 ; # small yo
|
||||
A4 BA ; # small Ukrainian ye
|
||||
|
||||
A6 B3 ; # small Ukrainian i
|
||||
A7 BF ; # small Ukrainian yi
|
||||
|
||||
AD B4 ; # small Ukrainian soft g
|
||||
AE A2 ; # small Byelorussian short u
|
||||
|
||||
B0 B0 ; # °
|
||||
|
||||
B3 A8 ; # capital YO
|
||||
B4 AA ; # capital Ukrainian YE
|
||||
|
||||
B6 B2 ; # capital Ukrainian I
|
||||
B7 AF ; # capital Ukrainian YI
|
||||
|
||||
B9 B9 ; # numero sign
|
||||
|
||||
BD A5 ; # capital Ukrainian soft G
|
||||
BE A1 ; # capital Byelorussian short U
|
||||
|
||||
BF A9 ; # (C)
|
||||
|
||||
C0 FE ; # small yu
|
||||
C1 E0 ; # small a
|
||||
C2 E1 ; # small b
|
||||
C3 F6 ; # small ts
|
||||
C4 E4 ; # small d
|
||||
C5 E5 ; # small ye
|
||||
C6 F4 ; # small f
|
||||
C7 E3 ; # small g
|
||||
C8 F5 ; # small kh
|
||||
C9 E8 ; # small i
|
||||
CA E9 ; # small j
|
||||
CB EA ; # small k
|
||||
CC EB ; # small l
|
||||
CD EC ; # small m
|
||||
CE ED ; # small n
|
||||
CF EE ; # small o
|
||||
|
||||
D0 EF ; # small p
|
||||
D1 FF ; # small ya
|
||||
D2 F0 ; # small r
|
||||
D3 F1 ; # small s
|
||||
D4 F2 ; # small t
|
||||
D5 F3 ; # small u
|
||||
D6 E6 ; # small zh
|
||||
D7 E2 ; # small v
|
||||
D8 FC ; # small soft sign
|
||||
D9 FB ; # small y
|
||||
DA E7 ; # small z
|
||||
DB F8 ; # small sh
|
||||
DC FD ; # small e
|
||||
DD F9 ; # small shch
|
||||
DE F7 ; # small ch
|
||||
DF FA ; # small hard sign
|
||||
|
||||
E0 DE ; # capital YU
|
||||
E1 C0 ; # capital A
|
||||
E2 C1 ; # capital B
|
||||
E3 D6 ; # capital TS
|
||||
E4 C4 ; # capital D
|
||||
E5 C5 ; # capital YE
|
||||
E6 D4 ; # capital F
|
||||
E7 C3 ; # capital G
|
||||
E8 D5 ; # capital KH
|
||||
E9 C8 ; # capital I
|
||||
EA C9 ; # capital J
|
||||
EB CA ; # capital K
|
||||
EC CB ; # capital L
|
||||
ED CC ; # capital M
|
||||
EE CD ; # capital N
|
||||
EF CE ; # capital O
|
||||
|
||||
F0 CF ; # capital P
|
||||
F1 DF ; # capital YA
|
||||
F2 D0 ; # capital R
|
||||
F3 D1 ; # capital S
|
||||
F4 D2 ; # capital T
|
||||
F5 D3 ; # capital U
|
||||
F6 C6 ; # capital ZH
|
||||
F7 C2 ; # capital V
|
||||
F8 DC ; # capital soft sign
|
||||
F9 DB ; # capital Y
|
||||
FA C7 ; # capital Z
|
||||
FB D8 ; # capital SH
|
||||
FC DD ; # capital E
|
||||
FD D9 ; # capital SHCH
|
||||
FE D7 ; # capital CH
|
||||
FF DA ; # capital hard sign
|
||||
}
|
99
nginx-1.28.0/conf/mime.types
Normal file
99
nginx-1.28.0/conf/mime.types
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
types {
|
||||
text/html html htm shtml;
|
||||
text/css css;
|
||||
text/xml xml;
|
||||
image/gif gif;
|
||||
image/jpeg jpeg jpg;
|
||||
application/javascript js;
|
||||
application/atom+xml atom;
|
||||
application/rss+xml rss;
|
||||
|
||||
text/mathml mml;
|
||||
text/plain txt;
|
||||
text/vnd.sun.j2me.app-descriptor jad;
|
||||
text/vnd.wap.wml wml;
|
||||
text/x-component htc;
|
||||
|
||||
image/avif avif;
|
||||
image/png png;
|
||||
image/svg+xml svg svgz;
|
||||
image/tiff tif tiff;
|
||||
image/vnd.wap.wbmp wbmp;
|
||||
image/webp webp;
|
||||
image/x-icon ico;
|
||||
image/x-jng jng;
|
||||
image/x-ms-bmp bmp;
|
||||
|
||||
font/woff woff;
|
||||
font/woff2 woff2;
|
||||
|
||||
application/java-archive jar war ear;
|
||||
application/json json;
|
||||
application/mac-binhex40 hqx;
|
||||
application/msword doc;
|
||||
application/pdf pdf;
|
||||
application/postscript ps eps ai;
|
||||
application/rtf rtf;
|
||||
application/vnd.apple.mpegurl m3u8;
|
||||
application/vnd.google-earth.kml+xml kml;
|
||||
application/vnd.google-earth.kmz kmz;
|
||||
application/vnd.ms-excel xls;
|
||||
application/vnd.ms-fontobject eot;
|
||||
application/vnd.ms-powerpoint ppt;
|
||||
application/vnd.oasis.opendocument.graphics odg;
|
||||
application/vnd.oasis.opendocument.presentation odp;
|
||||
application/vnd.oasis.opendocument.spreadsheet ods;
|
||||
application/vnd.oasis.opendocument.text odt;
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
pptx;
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
xlsx;
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
docx;
|
||||
application/vnd.wap.wmlc wmlc;
|
||||
application/wasm wasm;
|
||||
application/x-7z-compressed 7z;
|
||||
application/x-cocoa cco;
|
||||
application/x-java-archive-diff jardiff;
|
||||
application/x-java-jnlp-file jnlp;
|
||||
application/x-makeself run;
|
||||
application/x-perl pl pm;
|
||||
application/x-pilot prc pdb;
|
||||
application/x-rar-compressed rar;
|
||||
application/x-redhat-package-manager rpm;
|
||||
application/x-sea sea;
|
||||
application/x-shockwave-flash swf;
|
||||
application/x-stuffit sit;
|
||||
application/x-tcl tcl tk;
|
||||
application/x-x509-ca-cert der pem crt;
|
||||
application/x-xpinstall xpi;
|
||||
application/xhtml+xml xhtml;
|
||||
application/xspf+xml xspf;
|
||||
application/zip zip;
|
||||
|
||||
application/octet-stream bin exe dll;
|
||||
application/octet-stream deb;
|
||||
application/octet-stream dmg;
|
||||
application/octet-stream iso img;
|
||||
application/octet-stream msi msp msm;
|
||||
|
||||
audio/midi mid midi kar;
|
||||
audio/mpeg mp3;
|
||||
audio/ogg ogg;
|
||||
audio/x-m4a m4a;
|
||||
audio/x-realaudio ra;
|
||||
|
||||
video/3gpp 3gpp 3gp;
|
||||
video/mp2t ts;
|
||||
video/mp4 mp4;
|
||||
video/mpeg mpeg mpg;
|
||||
video/quicktime mov;
|
||||
video/webm webm;
|
||||
video/x-flv flv;
|
||||
video/x-m4v m4v;
|
||||
video/x-mng mng;
|
||||
video/x-ms-asf asx asf;
|
||||
video/x-ms-wmv wmv;
|
||||
video/x-msvideo avi;
|
||||
}
|
38
nginx-1.28.0/conf/nginx.conf
Normal file
38
nginx-1.28.0/conf/nginx.conf
Normal file
@@ -0,0 +1,38 @@
|
||||
# ./nginx/nginx.conf
|
||||
|
||||
# 이벤트 블록은 Nginx가 어떻게 연결을 처리할지 정의합니다.
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
# HTTP 블록은 웹 서버의 동작을 정의합니다.
|
||||
http {
|
||||
# MIME 타입 파일을 포함하여 파일 확장자에 따라 콘텐츠 타입을 결정합니다.
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
# 기본 서버 설정을 정의합니다.
|
||||
server {
|
||||
# 80번 포트에서 요청을 받습니다.
|
||||
listen 80;
|
||||
server_name localhost; # 서버 이름을 localhost로 설정
|
||||
|
||||
# 루트 경로(/)로 들어오는 모든 요청을 처리합니다.
|
||||
location / {
|
||||
# 요청을 다른 서버(여기서는 Nuxt.js)로 전달합니다.
|
||||
proxy_pass http://localhost:3000;
|
||||
|
||||
# 프록시 헤더를 설정하여 원본 요청 정보를 유지합니다.
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# /api/ 경로로 들어오는 요청을 처리합니다. (Spring Boot 컨테이너를 가리킨다고 가정)
|
||||
location /service {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
}
|
17
nginx-1.28.0/conf/scgi_params
Normal file
17
nginx-1.28.0/conf/scgi_params
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
scgi_param REQUEST_METHOD $request_method;
|
||||
scgi_param REQUEST_URI $request_uri;
|
||||
scgi_param QUERY_STRING $query_string;
|
||||
scgi_param CONTENT_TYPE $content_type;
|
||||
|
||||
scgi_param DOCUMENT_URI $document_uri;
|
||||
scgi_param DOCUMENT_ROOT $document_root;
|
||||
scgi_param SCGI 1;
|
||||
scgi_param SERVER_PROTOCOL $server_protocol;
|
||||
scgi_param REQUEST_SCHEME $scheme;
|
||||
scgi_param HTTPS $https if_not_empty;
|
||||
|
||||
scgi_param REMOTE_ADDR $remote_addr;
|
||||
scgi_param REMOTE_PORT $remote_port;
|
||||
scgi_param SERVER_PORT $server_port;
|
||||
scgi_param SERVER_NAME $server_name;
|
17
nginx-1.28.0/conf/uwsgi_params
Normal file
17
nginx-1.28.0/conf/uwsgi_params
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
uwsgi_param QUERY_STRING $query_string;
|
||||
uwsgi_param REQUEST_METHOD $request_method;
|
||||
uwsgi_param CONTENT_TYPE $content_type;
|
||||
uwsgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
uwsgi_param REQUEST_URI $request_uri;
|
||||
uwsgi_param PATH_INFO $document_uri;
|
||||
uwsgi_param DOCUMENT_ROOT $document_root;
|
||||
uwsgi_param SERVER_PROTOCOL $server_protocol;
|
||||
uwsgi_param REQUEST_SCHEME $scheme;
|
||||
uwsgi_param HTTPS $https if_not_empty;
|
||||
|
||||
uwsgi_param REMOTE_ADDR $remote_addr;
|
||||
uwsgi_param REMOTE_PORT $remote_port;
|
||||
uwsgi_param SERVER_PORT $server_port;
|
||||
uwsgi_param SERVER_NAME $server_name;
|
126
nginx-1.28.0/conf/win-utf
Normal file
126
nginx-1.28.0/conf/win-utf
Normal file
@@ -0,0 +1,126 @@
|
||||
|
||||
# This map is not a full windows-1251 <> utf8 map: it does not
|
||||
# contain Serbian and Macedonian letters. If you need a full map,
|
||||
# use contrib/unicode2nginx/win-utf map instead.
|
||||
|
||||
charset_map windows-1251 utf-8 {
|
||||
|
||||
82 E2809A ; # single low-9 quotation mark
|
||||
|
||||
84 E2809E ; # double low-9 quotation mark
|
||||
85 E280A6 ; # ellipsis
|
||||
86 E280A0 ; # dagger
|
||||
87 E280A1 ; # double dagger
|
||||
88 E282AC ; # euro
|
||||
89 E280B0 ; # per mille
|
||||
|
||||
91 E28098 ; # left single quotation mark
|
||||
92 E28099 ; # right single quotation mark
|
||||
93 E2809C ; # left double quotation mark
|
||||
94 E2809D ; # right double quotation mark
|
||||
95 E280A2 ; # bullet
|
||||
96 E28093 ; # en dash
|
||||
97 E28094 ; # em dash
|
||||
|
||||
99 E284A2 ; # trade mark sign
|
||||
|
||||
A0 C2A0 ; #
|
||||
A1 D18E ; # capital Byelorussian short U
|
||||
A2 D19E ; # small Byelorussian short u
|
||||
|
||||
A4 C2A4 ; # currency sign
|
||||
A5 D290 ; # capital Ukrainian soft G
|
||||
A6 C2A6 ; # borken bar
|
||||
A7 C2A7 ; # section sign
|
||||
A8 D081 ; # capital YO
|
||||
A9 C2A9 ; # (C)
|
||||
AA D084 ; # capital Ukrainian YE
|
||||
AB C2AB ; # left-pointing double angle quotation mark
|
||||
AC C2AC ; # not sign
|
||||
AD C2AD ; # soft hyphen
|
||||
AE C2AE ; # (R)
|
||||
AF D087 ; # capital Ukrainian YI
|
||||
|
||||
B0 C2B0 ; # °
|
||||
B1 C2B1 ; # plus-minus sign
|
||||
B2 D086 ; # capital Ukrainian I
|
||||
B3 D196 ; # small Ukrainian i
|
||||
B4 D291 ; # small Ukrainian soft g
|
||||
B5 C2B5 ; # micro sign
|
||||
B6 C2B6 ; # pilcrow sign
|
||||
B7 C2B7 ; # ·
|
||||
B8 D191 ; # small yo
|
||||
B9 E28496 ; # numero sign
|
||||
BA D194 ; # small Ukrainian ye
|
||||
BB C2BB ; # right-pointing double angle quotation mark
|
||||
|
||||
BF D197 ; # small Ukrainian yi
|
||||
|
||||
C0 D090 ; # capital A
|
||||
C1 D091 ; # capital B
|
||||
C2 D092 ; # capital V
|
||||
C3 D093 ; # capital G
|
||||
C4 D094 ; # capital D
|
||||
C5 D095 ; # capital YE
|
||||
C6 D096 ; # capital ZH
|
||||
C7 D097 ; # capital Z
|
||||
C8 D098 ; # capital I
|
||||
C9 D099 ; # capital J
|
||||
CA D09A ; # capital K
|
||||
CB D09B ; # capital L
|
||||
CC D09C ; # capital M
|
||||
CD D09D ; # capital N
|
||||
CE D09E ; # capital O
|
||||
CF D09F ; # capital P
|
||||
|
||||
D0 D0A0 ; # capital R
|
||||
D1 D0A1 ; # capital S
|
||||
D2 D0A2 ; # capital T
|
||||
D3 D0A3 ; # capital U
|
||||
D4 D0A4 ; # capital F
|
||||
D5 D0A5 ; # capital KH
|
||||
D6 D0A6 ; # capital TS
|
||||
D7 D0A7 ; # capital CH
|
||||
D8 D0A8 ; # capital SH
|
||||
D9 D0A9 ; # capital SHCH
|
||||
DA D0AA ; # capital hard sign
|
||||
DB D0AB ; # capital Y
|
||||
DC D0AC ; # capital soft sign
|
||||
DD D0AD ; # capital E
|
||||
DE D0AE ; # capital YU
|
||||
DF D0AF ; # capital YA
|
||||
|
||||
E0 D0B0 ; # small a
|
||||
E1 D0B1 ; # small b
|
||||
E2 D0B2 ; # small v
|
||||
E3 D0B3 ; # small g
|
||||
E4 D0B4 ; # small d
|
||||
E5 D0B5 ; # small ye
|
||||
E6 D0B6 ; # small zh
|
||||
E7 D0B7 ; # small z
|
||||
E8 D0B8 ; # small i
|
||||
E9 D0B9 ; # small j
|
||||
EA D0BA ; # small k
|
||||
EB D0BB ; # small l
|
||||
EC D0BC ; # small m
|
||||
ED D0BD ; # small n
|
||||
EE D0BE ; # small o
|
||||
EF D0BF ; # small p
|
||||
|
||||
F0 D180 ; # small r
|
||||
F1 D181 ; # small s
|
||||
F2 D182 ; # small t
|
||||
F3 D183 ; # small u
|
||||
F4 D184 ; # small f
|
||||
F5 D185 ; # small kh
|
||||
F6 D186 ; # small ts
|
||||
F7 D187 ; # small ch
|
||||
F8 D188 ; # small sh
|
||||
F9 D189 ; # small shch
|
||||
FA D18A ; # small hard sign
|
||||
FB D18B ; # small y
|
||||
FC D18C ; # small soft sign
|
||||
FD D18D ; # small e
|
||||
FE D18E ; # small yu
|
||||
FF D18F ; # small ya
|
||||
}
|
21
nginx-1.28.0/contrib/README
Normal file
21
nginx-1.28.0/contrib/README
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
geo2nginx.pl by Andrei Nigmatulin
|
||||
|
||||
The perl script to convert CSV geoip database ( free download
|
||||
at http://www.maxmind.com/app/geoip_country ) to format, suitable
|
||||
for use by the ngx_http_geo_module.
|
||||
|
||||
|
||||
unicode2nginx by Maxim Dounin
|
||||
|
||||
The perl script to convert unicode mappings ( available
|
||||
at http://www.unicode.org/Public/MAPPINGS/ ) to the nginx
|
||||
configuration file format.
|
||||
Two generated full maps for windows-1251 and koi8-r.
|
||||
|
||||
|
||||
vim by Evan Miller
|
||||
|
||||
Syntax highlighting of nginx configuration for vim, to be
|
||||
placed into ~/.vim/.
|
||||
|
58
nginx-1.28.0/contrib/geo2nginx.pl
Normal file
58
nginx-1.28.0/contrib/geo2nginx.pl
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# (c) Andrei Nigmatulin, 2005
|
||||
#
|
||||
# this script provided "as is", without any warranties. use it at your own risk.
|
||||
#
|
||||
# special thanx to Andrew Sitnikov for perl port
|
||||
#
|
||||
# this script converts CSV geoip database (free download at http://www.maxmind.com/app/geoip_country)
|
||||
# to format, suitable for use with nginx_http_geo module (http://sysoev.ru/nginx)
|
||||
#
|
||||
# for example, line with ip range
|
||||
#
|
||||
# "62.16.68.0","62.16.127.255","1041253376","1041268735","RU","Russian Federation"
|
||||
#
|
||||
# will be converted to four subnetworks:
|
||||
#
|
||||
# 62.16.68.0/22 RU;
|
||||
# 62.16.72.0/21 RU;
|
||||
# 62.16.80.0/20 RU;
|
||||
# 62.16.96.0/19 RU;
|
||||
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
while( <STDIN> ){
|
||||
if (/"[^"]+","[^"]+","([^"]+)","([^"]+)","([^"]+)"/){
|
||||
print_subnets($1, $2, $3);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_subnets {
|
||||
my ($a1, $a2, $c) = @_;
|
||||
my $l;
|
||||
while ($a1 <= $a2) {
|
||||
for ($l = 0; ($a1 & (1 << $l)) == 0 && ($a1 + ((1 << ($l + 1)) - 1)) <= $a2; $l++){};
|
||||
print long2ip($a1) . "/" . (32 - $l) . " " . $c . ";\n";
|
||||
$a1 += (1 << $l);
|
||||
}
|
||||
}
|
||||
|
||||
sub long2ip {
|
||||
my $ip = shift;
|
||||
|
||||
my $str = 0;
|
||||
|
||||
$str = ($ip & 255);
|
||||
|
||||
$ip >>= 8;
|
||||
$str = ($ip & 255).".$str";
|
||||
|
||||
$ip >>= 8;
|
||||
$str = ($ip & 255).".$str";
|
||||
|
||||
$ip >>= 8;
|
||||
$str = ($ip & 255).".$str";
|
||||
}
|
131
nginx-1.28.0/contrib/unicode2nginx/koi-utf
Normal file
131
nginx-1.28.0/contrib/unicode2nginx/koi-utf
Normal file
@@ -0,0 +1,131 @@
|
||||
charset_map koi8-r utf-8 {
|
||||
|
||||
80 E29480 ; # BOX DRAWINGS LIGHT HORIZONTAL
|
||||
81 E29482 ; # BOX DRAWINGS LIGHT VERTICAL
|
||||
82 E2948C ; # BOX DRAWINGS LIGHT DOWN AND RIGHT
|
||||
83 E29490 ; # BOX DRAWINGS LIGHT DOWN AND LEFT
|
||||
84 E29494 ; # BOX DRAWINGS LIGHT UP AND RIGHT
|
||||
85 E29498 ; # BOX DRAWINGS LIGHT UP AND LEFT
|
||||
86 E2949C ; # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||
87 E294A4 ; # BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||
88 E294AC ; # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||
89 E294B4 ; # BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||
8A E294BC ; # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
|
||||
8B E29680 ; # UPPER HALF BLOCK
|
||||
8C E29684 ; # LOWER HALF BLOCK
|
||||
8D E29688 ; # FULL BLOCK
|
||||
8E E2968C ; # LEFT HALF BLOCK
|
||||
8F E29690 ; # RIGHT HALF BLOCK
|
||||
90 E29691 ; # LIGHT SHADE
|
||||
91 E29692 ; # MEDIUM SHADE
|
||||
92 E29693 ; # DARK SHADE
|
||||
93 E28CA0 ; # TOP HALF INTEGRAL
|
||||
94 E296A0 ; # BLACK SQUARE
|
||||
95 E28899 ; # BULLET OPERATOR
|
||||
96 E2889A ; # SQUARE ROOT
|
||||
97 E28988 ; # ALMOST EQUAL TO
|
||||
98 E289A4 ; # LESS-THAN OR EQUAL TO
|
||||
99 E289A5 ; # GREATER-THAN OR EQUAL TO
|
||||
9A C2A0 ; # NO-BREAK SPACE
|
||||
9B E28CA1 ; # BOTTOM HALF INTEGRAL
|
||||
9C C2B0 ; # DEGREE SIGN
|
||||
9D C2B2 ; # SUPERSCRIPT TWO
|
||||
9E C2B7 ; # MIDDLE DOT
|
||||
9F C3B7 ; # DIVISION SIGN
|
||||
A0 E29590 ; # BOX DRAWINGS DOUBLE HORIZONTAL
|
||||
A1 E29591 ; # BOX DRAWINGS DOUBLE VERTICAL
|
||||
A2 E29592 ; # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
|
||||
A3 D191 ; # CYRILLIC SMALL LETTER IO
|
||||
A4 E29593 ; # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
|
||||
A5 E29594 ; # BOX DRAWINGS DOUBLE DOWN AND RIGHT
|
||||
A6 E29595 ; # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
|
||||
A7 E29596 ; # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
|
||||
A8 E29597 ; # BOX DRAWINGS DOUBLE DOWN AND LEFT
|
||||
A9 E29598 ; # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
|
||||
AA E29599 ; # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
|
||||
AB E2959A ; # BOX DRAWINGS DOUBLE UP AND RIGHT
|
||||
AC E2959B ; # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
|
||||
AD E2959C ; # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
|
||||
AE E2959D ; # BOX DRAWINGS DOUBLE UP AND LEFT
|
||||
AF E2959E ; # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
|
||||
B0 E2959F ; # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
|
||||
B1 E295A0 ; # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
|
||||
B2 E295A1 ; # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
|
||||
B3 D081 ; # CYRILLIC CAPITAL LETTER IO
|
||||
B4 E295A2 ; # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
|
||||
B5 E295A3 ; # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
|
||||
B6 E295A4 ; # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
|
||||
B7 E295A5 ; # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
|
||||
B8 E295A6 ; # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
|
||||
B9 E295A7 ; # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
|
||||
BA E295A8 ; # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
|
||||
BB E295A9 ; # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
|
||||
BC E295AA ; # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
|
||||
BD E295AB ; # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
|
||||
BE E295AC ; # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
|
||||
BF C2A9 ; # COPYRIGHT SIGN
|
||||
C0 D18E ; # CYRILLIC SMALL LETTER YU
|
||||
C1 D0B0 ; # CYRILLIC SMALL LETTER A
|
||||
C2 D0B1 ; # CYRILLIC SMALL LETTER BE
|
||||
C3 D186 ; # CYRILLIC SMALL LETTER TSE
|
||||
C4 D0B4 ; # CYRILLIC SMALL LETTER DE
|
||||
C5 D0B5 ; # CYRILLIC SMALL LETTER IE
|
||||
C6 D184 ; # CYRILLIC SMALL LETTER EF
|
||||
C7 D0B3 ; # CYRILLIC SMALL LETTER GHE
|
||||
C8 D185 ; # CYRILLIC SMALL LETTER HA
|
||||
C9 D0B8 ; # CYRILLIC SMALL LETTER I
|
||||
CA D0B9 ; # CYRILLIC SMALL LETTER SHORT I
|
||||
CB D0BA ; # CYRILLIC SMALL LETTER KA
|
||||
CC D0BB ; # CYRILLIC SMALL LETTER EL
|
||||
CD D0BC ; # CYRILLIC SMALL LETTER EM
|
||||
CE D0BD ; # CYRILLIC SMALL LETTER EN
|
||||
CF D0BE ; # CYRILLIC SMALL LETTER O
|
||||
D0 D0BF ; # CYRILLIC SMALL LETTER PE
|
||||
D1 D18F ; # CYRILLIC SMALL LETTER YA
|
||||
D2 D180 ; # CYRILLIC SMALL LETTER ER
|
||||
D3 D181 ; # CYRILLIC SMALL LETTER ES
|
||||
D4 D182 ; # CYRILLIC SMALL LETTER TE
|
||||
D5 D183 ; # CYRILLIC SMALL LETTER U
|
||||
D6 D0B6 ; # CYRILLIC SMALL LETTER ZHE
|
||||
D7 D0B2 ; # CYRILLIC SMALL LETTER VE
|
||||
D8 D18C ; # CYRILLIC SMALL LETTER SOFT SIGN
|
||||
D9 D18B ; # CYRILLIC SMALL LETTER YERU
|
||||
DA D0B7 ; # CYRILLIC SMALL LETTER ZE
|
||||
DB D188 ; # CYRILLIC SMALL LETTER SHA
|
||||
DC D18D ; # CYRILLIC SMALL LETTER E
|
||||
DD D189 ; # CYRILLIC SMALL LETTER SHCHA
|
||||
DE D187 ; # CYRILLIC SMALL LETTER CHE
|
||||
DF D18A ; # CYRILLIC SMALL LETTER HARD SIGN
|
||||
E0 D0AE ; # CYRILLIC CAPITAL LETTER YU
|
||||
E1 D090 ; # CYRILLIC CAPITAL LETTER A
|
||||
E2 D091 ; # CYRILLIC CAPITAL LETTER BE
|
||||
E3 D0A6 ; # CYRILLIC CAPITAL LETTER TSE
|
||||
E4 D094 ; # CYRILLIC CAPITAL LETTER DE
|
||||
E5 D095 ; # CYRILLIC CAPITAL LETTER IE
|
||||
E6 D0A4 ; # CYRILLIC CAPITAL LETTER EF
|
||||
E7 D093 ; # CYRILLIC CAPITAL LETTER GHE
|
||||
E8 D0A5 ; # CYRILLIC CAPITAL LETTER HA
|
||||
E9 D098 ; # CYRILLIC CAPITAL LETTER I
|
||||
EA D099 ; # CYRILLIC CAPITAL LETTER SHORT I
|
||||
EB D09A ; # CYRILLIC CAPITAL LETTER KA
|
||||
EC D09B ; # CYRILLIC CAPITAL LETTER EL
|
||||
ED D09C ; # CYRILLIC CAPITAL LETTER EM
|
||||
EE D09D ; # CYRILLIC CAPITAL LETTER EN
|
||||
EF D09E ; # CYRILLIC CAPITAL LETTER O
|
||||
F0 D09F ; # CYRILLIC CAPITAL LETTER PE
|
||||
F1 D0AF ; # CYRILLIC CAPITAL LETTER YA
|
||||
F2 D0A0 ; # CYRILLIC CAPITAL LETTER ER
|
||||
F3 D0A1 ; # CYRILLIC CAPITAL LETTER ES
|
||||
F4 D0A2 ; # CYRILLIC CAPITAL LETTER TE
|
||||
F5 D0A3 ; # CYRILLIC CAPITAL LETTER U
|
||||
F6 D096 ; # CYRILLIC CAPITAL LETTER ZHE
|
||||
F7 D092 ; # CYRILLIC CAPITAL LETTER VE
|
||||
F8 D0AC ; # CYRILLIC CAPITAL LETTER SOFT SIGN
|
||||
F9 D0AB ; # CYRILLIC CAPITAL LETTER YERU
|
||||
FA D097 ; # CYRILLIC CAPITAL LETTER ZE
|
||||
FB D0A8 ; # CYRILLIC CAPITAL LETTER SHA
|
||||
FC D0AD ; # CYRILLIC CAPITAL LETTER E
|
||||
FD D0A9 ; # CYRILLIC CAPITAL LETTER SHCHA
|
||||
FE D0A7 ; # CYRILLIC CAPITAL LETTER CHE
|
||||
FF D0AA ; # CYRILLIC CAPITAL LETTER HARD SIGN
|
||||
}
|
48
nginx-1.28.0/contrib/unicode2nginx/unicode-to-nginx.pl
Normal file
48
nginx-1.28.0/contrib/unicode2nginx/unicode-to-nginx.pl
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# Convert unicode mappings to nginx configuration file format.
|
||||
|
||||
# You may find useful mappings in various places, including
|
||||
# unicode.org official site:
|
||||
#
|
||||
# http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
|
||||
# http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT
|
||||
|
||||
# Needs perl 5.6 or later.
|
||||
|
||||
# Written by Maxim Dounin, mdounin@mdounin.ru
|
||||
|
||||
###############################################################################
|
||||
|
||||
require 5.006;
|
||||
|
||||
while (<>) {
|
||||
# Skip comments and empty lines
|
||||
|
||||
next if /^#/;
|
||||
next if /^\s*$/;
|
||||
chomp;
|
||||
|
||||
# Convert mappings
|
||||
|
||||
if (/^\s*0x(..)\s*0x(....)\s*(#.*)/) {
|
||||
# Mapping <from-code> <unicode-code> "#" <unicode-name>
|
||||
my $cs_code = $1;
|
||||
my $un_code = $2;
|
||||
my $un_name = $3;
|
||||
|
||||
# Produce UTF-8 sequence from character code;
|
||||
|
||||
my $un_utf8 = join('',
|
||||
map { sprintf("%02X", $_) }
|
||||
unpack("U0C*", pack("U", hex($un_code)))
|
||||
);
|
||||
|
||||
print " $cs_code $un_utf8 ; $un_name\n";
|
||||
|
||||
} else {
|
||||
warn "Unrecognized line: '$_'";
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
130
nginx-1.28.0/contrib/unicode2nginx/win-utf
Normal file
130
nginx-1.28.0/contrib/unicode2nginx/win-utf
Normal file
@@ -0,0 +1,130 @@
|
||||
charset_map windows-1251 utf-8 {
|
||||
|
||||
80 D082 ; #CYRILLIC CAPITAL LETTER DJE
|
||||
81 D083 ; #CYRILLIC CAPITAL LETTER GJE
|
||||
82 E2809A ; #SINGLE LOW-9 QUOTATION MARK
|
||||
83 D193 ; #CYRILLIC SMALL LETTER GJE
|
||||
84 E2809E ; #DOUBLE LOW-9 QUOTATION MARK
|
||||
85 E280A6 ; #HORIZONTAL ELLIPSIS
|
||||
86 E280A0 ; #DAGGER
|
||||
87 E280A1 ; #DOUBLE DAGGER
|
||||
88 E282AC ; #EURO SIGN
|
||||
89 E280B0 ; #PER MILLE SIGN
|
||||
8A D089 ; #CYRILLIC CAPITAL LETTER LJE
|
||||
8B E280B9 ; #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
|
||||
8C D08A ; #CYRILLIC CAPITAL LETTER NJE
|
||||
8D D08C ; #CYRILLIC CAPITAL LETTER KJE
|
||||
8E D08B ; #CYRILLIC CAPITAL LETTER TSHE
|
||||
8F D08F ; #CYRILLIC CAPITAL LETTER DZHE
|
||||
90 D192 ; #CYRILLIC SMALL LETTER DJE
|
||||
91 E28098 ; #LEFT SINGLE QUOTATION MARK
|
||||
92 E28099 ; #RIGHT SINGLE QUOTATION MARK
|
||||
93 E2809C ; #LEFT DOUBLE QUOTATION MARK
|
||||
94 E2809D ; #RIGHT DOUBLE QUOTATION MARK
|
||||
95 E280A2 ; #BULLET
|
||||
96 E28093 ; #EN DASH
|
||||
97 E28094 ; #EM DASH
|
||||
99 E284A2 ; #TRADE MARK SIGN
|
||||
9A D199 ; #CYRILLIC SMALL LETTER LJE
|
||||
9B E280BA ; #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
|
||||
9C D19A ; #CYRILLIC SMALL LETTER NJE
|
||||
9D D19C ; #CYRILLIC SMALL LETTER KJE
|
||||
9E D19B ; #CYRILLIC SMALL LETTER TSHE
|
||||
9F D19F ; #CYRILLIC SMALL LETTER DZHE
|
||||
A0 C2A0 ; #NO-BREAK SPACE
|
||||
A1 D08E ; #CYRILLIC CAPITAL LETTER SHORT U
|
||||
A2 D19E ; #CYRILLIC SMALL LETTER SHORT U
|
||||
A3 D088 ; #CYRILLIC CAPITAL LETTER JE
|
||||
A4 C2A4 ; #CURRENCY SIGN
|
||||
A5 D290 ; #CYRILLIC CAPITAL LETTER GHE WITH UPTURN
|
||||
A6 C2A6 ; #BROKEN BAR
|
||||
A7 C2A7 ; #SECTION SIGN
|
||||
A8 D081 ; #CYRILLIC CAPITAL LETTER IO
|
||||
A9 C2A9 ; #COPYRIGHT SIGN
|
||||
AA D084 ; #CYRILLIC CAPITAL LETTER UKRAINIAN IE
|
||||
AB C2AB ; #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
AC C2AC ; #NOT SIGN
|
||||
AD C2AD ; #SOFT HYPHEN
|
||||
AE C2AE ; #REGISTERED SIGN
|
||||
AF D087 ; #CYRILLIC CAPITAL LETTER YI
|
||||
B0 C2B0 ; #DEGREE SIGN
|
||||
B1 C2B1 ; #PLUS-MINUS SIGN
|
||||
B2 D086 ; #CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
|
||||
B3 D196 ; #CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
|
||||
B4 D291 ; #CYRILLIC SMALL LETTER GHE WITH UPTURN
|
||||
B5 C2B5 ; #MICRO SIGN
|
||||
B6 C2B6 ; #PILCROW SIGN
|
||||
B7 C2B7 ; #MIDDLE DOT
|
||||
B8 D191 ; #CYRILLIC SMALL LETTER IO
|
||||
B9 E28496 ; #NUMERO SIGN
|
||||
BA D194 ; #CYRILLIC SMALL LETTER UKRAINIAN IE
|
||||
BB C2BB ; #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
BC D198 ; #CYRILLIC SMALL LETTER JE
|
||||
BD D085 ; #CYRILLIC CAPITAL LETTER DZE
|
||||
BE D195 ; #CYRILLIC SMALL LETTER DZE
|
||||
BF D197 ; #CYRILLIC SMALL LETTER YI
|
||||
C0 D090 ; #CYRILLIC CAPITAL LETTER A
|
||||
C1 D091 ; #CYRILLIC CAPITAL LETTER BE
|
||||
C2 D092 ; #CYRILLIC CAPITAL LETTER VE
|
||||
C3 D093 ; #CYRILLIC CAPITAL LETTER GHE
|
||||
C4 D094 ; #CYRILLIC CAPITAL LETTER DE
|
||||
C5 D095 ; #CYRILLIC CAPITAL LETTER IE
|
||||
C6 D096 ; #CYRILLIC CAPITAL LETTER ZHE
|
||||
C7 D097 ; #CYRILLIC CAPITAL LETTER ZE
|
||||
C8 D098 ; #CYRILLIC CAPITAL LETTER I
|
||||
C9 D099 ; #CYRILLIC CAPITAL LETTER SHORT I
|
||||
CA D09A ; #CYRILLIC CAPITAL LETTER KA
|
||||
CB D09B ; #CYRILLIC CAPITAL LETTER EL
|
||||
CC D09C ; #CYRILLIC CAPITAL LETTER EM
|
||||
CD D09D ; #CYRILLIC CAPITAL LETTER EN
|
||||
CE D09E ; #CYRILLIC CAPITAL LETTER O
|
||||
CF D09F ; #CYRILLIC CAPITAL LETTER PE
|
||||
D0 D0A0 ; #CYRILLIC CAPITAL LETTER ER
|
||||
D1 D0A1 ; #CYRILLIC CAPITAL LETTER ES
|
||||
D2 D0A2 ; #CYRILLIC CAPITAL LETTER TE
|
||||
D3 D0A3 ; #CYRILLIC CAPITAL LETTER U
|
||||
D4 D0A4 ; #CYRILLIC CAPITAL LETTER EF
|
||||
D5 D0A5 ; #CYRILLIC CAPITAL LETTER HA
|
||||
D6 D0A6 ; #CYRILLIC CAPITAL LETTER TSE
|
||||
D7 D0A7 ; #CYRILLIC CAPITAL LETTER CHE
|
||||
D8 D0A8 ; #CYRILLIC CAPITAL LETTER SHA
|
||||
D9 D0A9 ; #CYRILLIC CAPITAL LETTER SHCHA
|
||||
DA D0AA ; #CYRILLIC CAPITAL LETTER HARD SIGN
|
||||
DB D0AB ; #CYRILLIC CAPITAL LETTER YERU
|
||||
DC D0AC ; #CYRILLIC CAPITAL LETTER SOFT SIGN
|
||||
DD D0AD ; #CYRILLIC CAPITAL LETTER E
|
||||
DE D0AE ; #CYRILLIC CAPITAL LETTER YU
|
||||
DF D0AF ; #CYRILLIC CAPITAL LETTER YA
|
||||
E0 D0B0 ; #CYRILLIC SMALL LETTER A
|
||||
E1 D0B1 ; #CYRILLIC SMALL LETTER BE
|
||||
E2 D0B2 ; #CYRILLIC SMALL LETTER VE
|
||||
E3 D0B3 ; #CYRILLIC SMALL LETTER GHE
|
||||
E4 D0B4 ; #CYRILLIC SMALL LETTER DE
|
||||
E5 D0B5 ; #CYRILLIC SMALL LETTER IE
|
||||
E6 D0B6 ; #CYRILLIC SMALL LETTER ZHE
|
||||
E7 D0B7 ; #CYRILLIC SMALL LETTER ZE
|
||||
E8 D0B8 ; #CYRILLIC SMALL LETTER I
|
||||
E9 D0B9 ; #CYRILLIC SMALL LETTER SHORT I
|
||||
EA D0BA ; #CYRILLIC SMALL LETTER KA
|
||||
EB D0BB ; #CYRILLIC SMALL LETTER EL
|
||||
EC D0BC ; #CYRILLIC SMALL LETTER EM
|
||||
ED D0BD ; #CYRILLIC SMALL LETTER EN
|
||||
EE D0BE ; #CYRILLIC SMALL LETTER O
|
||||
EF D0BF ; #CYRILLIC SMALL LETTER PE
|
||||
F0 D180 ; #CYRILLIC SMALL LETTER ER
|
||||
F1 D181 ; #CYRILLIC SMALL LETTER ES
|
||||
F2 D182 ; #CYRILLIC SMALL LETTER TE
|
||||
F3 D183 ; #CYRILLIC SMALL LETTER U
|
||||
F4 D184 ; #CYRILLIC SMALL LETTER EF
|
||||
F5 D185 ; #CYRILLIC SMALL LETTER HA
|
||||
F6 D186 ; #CYRILLIC SMALL LETTER TSE
|
||||
F7 D187 ; #CYRILLIC SMALL LETTER CHE
|
||||
F8 D188 ; #CYRILLIC SMALL LETTER SHA
|
||||
F9 D189 ; #CYRILLIC SMALL LETTER SHCHA
|
||||
FA D18A ; #CYRILLIC SMALL LETTER HARD SIGN
|
||||
FB D18B ; #CYRILLIC SMALL LETTER YERU
|
||||
FC D18C ; #CYRILLIC SMALL LETTER SOFT SIGN
|
||||
FD D18D ; #CYRILLIC SMALL LETTER E
|
||||
FE D18E ; #CYRILLIC SMALL LETTER YU
|
||||
FF D18F ; #CYRILLIC SMALL LETTER YA
|
||||
}
|
4
nginx-1.28.0/contrib/vim/ftdetect/nginx.vim
Normal file
4
nginx-1.28.0/contrib/vim/ftdetect/nginx.vim
Normal file
@@ -0,0 +1,4 @@
|
||||
au BufRead,BufNewFile *.nginx set ft=nginx
|
||||
au BufRead,BufNewFile */etc/nginx/* set ft=nginx
|
||||
au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx
|
||||
au BufRead,BufNewFile nginx.conf set ft=nginx
|
1
nginx-1.28.0/contrib/vim/ftplugin/nginx.vim
Normal file
1
nginx-1.28.0/contrib/vim/ftplugin/nginx.vim
Normal file
@@ -0,0 +1 @@
|
||||
setlocal commentstring=#\ %s
|
11
nginx-1.28.0/contrib/vim/indent/nginx.vim
Normal file
11
nginx-1.28.0/contrib/vim/indent/nginx.vim
Normal file
@@ -0,0 +1,11 @@
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal indentexpr=
|
||||
|
||||
" cindent actually works for nginx' simple file structure
|
||||
setlocal cindent
|
||||
" Just make sure that the comments are not reset as defs would be.
|
||||
setlocal cinkeys-=0#
|
1979
nginx-1.28.0/contrib/vim/syntax/nginx.vim
Normal file
1979
nginx-1.28.0/contrib/vim/syntax/nginx.vim
Normal file
File diff suppressed because it is too large
Load Diff
9290
nginx-1.28.0/docs/CHANGES
Normal file
9290
nginx-1.28.0/docs/CHANGES
Normal file
File diff suppressed because it is too large
Load Diff
9453
nginx-1.28.0/docs/CHANGES.ru
Normal file
9453
nginx-1.28.0/docs/CHANGES.ru
Normal file
File diff suppressed because it is too large
Load Diff
126
nginx-1.28.0/docs/CODE_OF_CONDUCT.md
Normal file
126
nginx-1.28.0/docs/CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes
|
||||
and learning from the experience
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- The use of sexualized language or imagery, and sexual attention or advances
|
||||
of any kind
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards
|
||||
of acceptable behavior and will take appropriate and fair corrective action
|
||||
in response to any behavior that they deem inappropriate, threatening,
|
||||
offensive, or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for
|
||||
moderation decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official email address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
<nginx-oss-community@f5.com>. All complaints will be reviewed and investigated
|
||||
promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external
|
||||
channels like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1,
|
||||
available at
|
||||
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion).
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
<https://www.contributor-covenant.org/faq>. Translations are available at
|
||||
<https://www.contributor-covenant.org/translations>.
|
110
nginx-1.28.0/docs/CONTRIBUTING.md
Normal file
110
nginx-1.28.0/docs/CONTRIBUTING.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
The following is a set of guidelines for contributing to nginx project.
|
||||
We really appreciate that you are considering contributing!
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Ask a Question](#ask-a-question)
|
||||
- [Report a Bug](#report-a-bug)
|
||||
- [Suggest a Feature or Enhancement](#suggest-a-feature-or-enhancement)
|
||||
- [Open a Discussion](#open-a-discussion)
|
||||
- [Submit a Pull Request](#submit-a-pull-request)
|
||||
- [Issue Lifecycle](#issue-lifecycle)
|
||||
|
||||
## Ask a Question
|
||||
|
||||
To ask a question, open an issue on GitHub with the label `question`.
|
||||
|
||||
## Report a Bug
|
||||
|
||||
To report a bug, open an issue on GitHub with the label `bug` using the
|
||||
available bug report issue template. Before reporting a bug, make sure the
|
||||
issue has not already been reported.
|
||||
|
||||
## Suggest a Feature or Enhancement
|
||||
|
||||
To suggest a feature or enhancement, open an issue on GitHub with the label
|
||||
`feature` or `enhancement` using the available feature request issue template.
|
||||
Please ensure the feature or enhancement has not already been suggested.
|
||||
|
||||
## Open a Discussion
|
||||
|
||||
If you want to engage in a conversation with the community and maintainers,
|
||||
we encourage you to use
|
||||
[GitHub Discussions](https://github.com/nginx/nginx/discussions).
|
||||
|
||||
## Submit a Pull Request
|
||||
|
||||
Follow this plan to contribute a change to NGINX source code:
|
||||
|
||||
- Fork the NGINX repository
|
||||
- Create a branch
|
||||
- Implement your changes in this branch
|
||||
- Submit a pull request (PR) when your changes are tested and ready for review
|
||||
|
||||
Refer to
|
||||
[NGINX Development Guide](https://nginx.org/en/docs/dev/development_guide.html)
|
||||
for questions about NGINX programming.
|
||||
|
||||
### Formatting Changes
|
||||
|
||||
- Changes should be formatted according to the
|
||||
[code style](https://nginx.org/en/docs/dev/development_guide.html#code_style)
|
||||
used by NGINX; sometimes, there is no clear rule, in which case examine how
|
||||
existing NGINX sources are formatted and mimic this style; changes will more
|
||||
likely be accepted if style corresponds to the surrounding code
|
||||
|
||||
- Keep a clean, concise and meaningful commit history on your branch, rebasing
|
||||
locally and breaking changes logically into commits before submitting a PR
|
||||
|
||||
- Each commit message should have a single-line subject line followed by verbose
|
||||
description after an empty line
|
||||
|
||||
- Limit the subject line to 67 characters, and the rest of the commit message
|
||||
to 76 characters
|
||||
|
||||
- Use subject line prefixes for commits that affect a specific portion of the
|
||||
code; examples include "Upstream:", "QUIC:", or "Core:"; see the commit history
|
||||
to get an idea of the prefixes used
|
||||
|
||||
- Reference issues in the the subject line; if the commit fixes an issue,
|
||||
[name it](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
|
||||
accordingly
|
||||
|
||||
### Before Submitting
|
||||
|
||||
- The proposed changes should work properly on a wide range of
|
||||
[supported platforms](https://nginx.org/en/index.html#tested_os_and_platforms)
|
||||
|
||||
- Try to make it clear why the suggested change is needed, and provide a use
|
||||
case, if possible
|
||||
|
||||
- Passing your changes through the test suite is a good way to ensure that they
|
||||
do not cause a regression; the repository with tests can be cloned with the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nginx/nginx-tests.git
|
||||
```
|
||||
|
||||
- Submitting a change implies granting project a permission to use it under the
|
||||
[BSD-2-Clause license](https://github.com/nginx/nginx/blob/master/LICENSE)
|
||||
|
||||
## Issue Lifecycle
|
||||
|
||||
To ensure a balance between work carried out by the NGINX engineering team
|
||||
while encouraging community involvement on this project, we use the following
|
||||
issue lifecycle:
|
||||
|
||||
- A new issue is created by a community member
|
||||
|
||||
- An owner on the NGINX engineering team is assigned to the issue; this
|
||||
owner shepherds the issue through the subsequent stages in the issue lifecycle
|
||||
|
||||
- The owner assigns one or more
|
||||
[labels](https://github.com/nginx/nginx/issues/labels) to the issue
|
||||
|
||||
- The owner, in collaboration with the wider team (product management and
|
||||
engineering), determines what milestone to attach to an issue;
|
||||
generally, milestones correspond to product releases
|
24
nginx-1.28.0/docs/LICENSE
Normal file
24
nginx-1.28.0/docs/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (C) 2002-2021 Igor Sysoev
|
||||
Copyright (C) 2011-2025 Nginx, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
177
nginx-1.28.0/docs/OpenSSL.LICENSE
Normal file
177
nginx-1.28.0/docs/OpenSSL.LICENSE
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
94
nginx-1.28.0/docs/PCRE.LICENCE
Normal file
94
nginx-1.28.0/docs/PCRE.LICENCE
Normal file
@@ -0,0 +1,94 @@
|
||||
PCRE2 LICENCE
|
||||
-------------
|
||||
|
||||
PCRE2 is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
|
||||
licence, as specified below, with one exemption for certain binary
|
||||
redistributions. The documentation for PCRE2, supplied in the "doc" directory,
|
||||
is distributed under the same terms as the software itself. The data in the
|
||||
testdata directory is not copyrighted and is in the public domain.
|
||||
|
||||
The basic library functions are written in C and are freestanding. Also
|
||||
included in the distribution is a just-in-time compiler that can be used to
|
||||
optimize pattern matching. This is an optional feature that can be omitted when
|
||||
the library is built.
|
||||
|
||||
|
||||
THE BASIC LIBRARY FUNCTIONS
|
||||
---------------------------
|
||||
|
||||
Written by: Philip Hazel
|
||||
Email local part: Philip.Hazel
|
||||
Email domain: gmail.com
|
||||
|
||||
Retired from University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2021 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
PCRE2 JUST-IN-TIME COMPILATION SUPPORT
|
||||
--------------------------------------
|
||||
|
||||
Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Email domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2021 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
STACK-LESS JUST-IN-TIME COMPILER
|
||||
--------------------------------
|
||||
|
||||
Written by: Zoltan Herczeg
|
||||
Email local part: hzmester
|
||||
Email domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2021 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
THE "BSD" LICENCE
|
||||
-----------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notices,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notices, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of any
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
|
||||
------------------------------------------
|
||||
|
||||
The second condition in the BSD licence (covering binary redistributions) does
|
||||
not apply all the way down a chain of software. If binary package A includes
|
||||
PCRE2, it must respect the condition, but if package B is software that
|
||||
includes package A, the condition is not imposed on package B unless it uses
|
||||
PCRE2 independently.
|
||||
|
||||
End
|
230
nginx-1.28.0/docs/README.md
Normal file
230
nginx-1.28.0/docs/README.md
Normal file
@@ -0,0 +1,230 @@
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/9335b488-ffcc-4157-8364-2370a0b70ad0">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/3a7eeb08-1133-47f5-859c-fad4f5a6a013">
|
||||
<img alt="NGINX Banner">
|
||||
</picture>
|
||||
|
||||
NGINX (pronounced "engine x" or "en-jin-eks") is the world's most popular Web Server, high performance Load Balancer, Reverse Proxy, API Gateway and Content Cache.
|
||||
|
||||
NGINX is free and open source software, distributed under the terms of a simplified [2-clause BSD-like license](LICENSE).
|
||||
|
||||
Enterprise distributions, commercial support and training are available from [F5, Inc](https://www.f5.com/products/nginx).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The goal of this README is to provide a basic, structured introduction to NGINX for novice users. Please refer to the [full NGINX documentation](https://nginx.org/en/docs/) for detailed information on [installing](https://nginx.org/en/docs/install.html), [building](https://nginx.org/en/docs/configure.html), [configuring](https://nginx.org/en/docs/dirindex.html), [debugging](https://nginx.org/en/docs/debugging_log.html), and more. These documentation pages also contain a more detailed [Beginners Guide](https://nginx.org/en/docs/beginners_guide.html), How-Tos, [Development guide](https://nginx.org/en/docs/dev/development_guide.html), and a complete module and [directive reference](https://nginx.org/en/docs/dirindex.html).
|
||||
|
||||
# Table of contents
|
||||
- [How it works](#how-it-works)
|
||||
- [Modules](#modules)
|
||||
- [Configurations](#configurations)
|
||||
- [Runtime](#runtime)
|
||||
- [Downloading and installing](#downloading-and-installing)
|
||||
- [Stable and Mainline binaries](#stable-and-mainline-binaries)
|
||||
- [Linux binary installation process](#linux-binary-installation-process)
|
||||
- [FreeBSD installation process](#freebsd-installation-process)
|
||||
- [Windows executables](#windows-executables)
|
||||
- [Dynamic modules](#dynamic-modules)
|
||||
- [Getting started with NGINX](#getting-started-with-nginx)
|
||||
- [Installing SSL certificates and enabling TLS encryption](#installing-ssl-certificates-and-enabling-tls-encryption)
|
||||
- [Load Balancing](#load-balancing)
|
||||
- [Rate limiting](#rate-limiting)
|
||||
- [Content caching](#content-caching)
|
||||
- [Building from source](#building-from-source)
|
||||
- [Installing dependencies](#installing-dependencies)
|
||||
- [Cloning the NGINX GitHub repository](#cloning-the-nginx-github-repository)
|
||||
- [Configuring the build](#configuring-the-build)
|
||||
- [Compiling](#compiling)
|
||||
- [Location of binary and installation](#location-of-binary-and-installation)
|
||||
- [Running and testing the installed binary](#running-and-testing-the-installed-binary)
|
||||
- [Asking questions and reporting issues](#asking-questions-and-reporting-issues)
|
||||
- [Contributing code](#contributing-code)
|
||||
- [Additional help and resources](#additional-help-and-resources)
|
||||
- [Changelog](#changelog)
|
||||
- [License](#license)
|
||||
|
||||
# How it works
|
||||
NGINX is installed software with binary packages available for all major operating systems and Linux distributions. See [Tested OS and Platforms](https://nginx.org/en/#tested_os_and_platforms) for a full list of compatible systems.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> While nearly all popular Linux-based operating systems are distributed with a community version of nginx, we highly advise installation and usage of official [packages](https://nginx.org/en/linux_packages.html) or sources from this repository. Doing so ensures that you're using the most recent release or source code, including the latest feature-set, fixes and security patches.
|
||||
|
||||
## Modules
|
||||
NGINX is comprised of individual modules, each extending core functionality by providing additional, configurable features. See "Modules reference" at the bottom of [nginx documentation](https://nginx.org/en/docs/) for a complete list of official modules.
|
||||
|
||||
NGINX modules can be built and distributed as static or dynamic modules. Static modules are defined at build-time, compiled, and distributed in the resulting binaries. See [Dynamic Modules](#dynamic-modules) for more information on how they work, as well as, how to obtain, install, and configure them.
|
||||
|
||||
> [!TIP]
|
||||
> You can issue the following command to see which static modules your NGINX binaries were built with:
|
||||
```bash
|
||||
nginx -V
|
||||
```
|
||||
> See [Configuring the build](#configuring-the-build) for information on how to include specific Static modules into your nginx build.
|
||||
|
||||
|
||||
## Configurations
|
||||
NGINX is highly flexible and configurable. Provisioning the software is achieved via text-based config file(s) accepting parameters called "[Directives](https://nginx.org/en/docs/dirindex.html)". See [Configuration File's Structure](https://nginx.org/en/docs/beginners_guide.html#conf_structure) for a comprehensive description of how NGINX configuration files work.
|
||||
|
||||
> [!NOTE]
|
||||
> The set of directives available to your distribution of NGINX is dependent on which [modules](#modules) have been made available to it.
|
||||
|
||||
## Runtime
|
||||
Rather than running in a single, monolithic process, NGINX is architected to scale beyond Operating System process limitations by operating as a collection of processes. They include:
|
||||
- A "master" process that maintains worker processes, as well as, reads and evaluates configuration files.
|
||||
- One or more "worker" processes that process data (eg. HTTP requests).
|
||||
|
||||
The number of [worker processes](https://nginx.org/en/docs/ngx_core_module.html#worker_processes) is defined in the configuration file and may be fixed for a given configuration or automatically adjusted to the number of available CPU cores. In most cases, the latter option optimally balances load across available system resources, as NGINX is designed to efficiently distribute work across all worker processes.
|
||||
|
||||
> [!TIP]
|
||||
> Processes synchronize data through shared memory. For this reason, many NGINX directives require the allocation of shared memory zones. As an example, when configuring [rate limiting](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req), connecting clients may need to be tracked in a [common memory zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone) so all worker processes can know how many times a particular client has accessed the server in a span of time.
|
||||
|
||||
# Downloading and installing
|
||||
Follow these steps to download and install precompiled NGINX binaries. You may also choose to [build NGINX locally from source code](#building-from-source).
|
||||
|
||||
## Stable and Mainline binaries
|
||||
NGINX binaries are built and distributed in two versions: stable and mainline. Stable binaries are built from stable branches and only contain critical fixes backported from the mainline version. Mainline binaries are built from the [master branch](https://github.com/nginx/nginx/tree/master) and contain the latest features and bugfixes. You'll need to [decide which is appropriate for your purposes](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#choosing-between-a-stable-or-a-mainline-version).
|
||||
|
||||
## Linux binary installation process
|
||||
The NGINX binary installation process takes advantage of package managers native to specific Linux distributions. For this reason, first-time installations involve adding the official NGINX package repository to your system's package manager. Follow [these steps](https://nginx.org/en/linux_packages.html) to download, verify, and install NGINX binaries using the package manager appropriate for your Linux distribution.
|
||||
|
||||
### Upgrades
|
||||
Future upgrades to the latest version can be managed using the same package manager without the need to manually download and verify binaries.
|
||||
|
||||
## FreeBSD installation process
|
||||
For more information on installing NGINX on FreeBSD system, visit https://nginx.org/en/docs/install.html
|
||||
|
||||
## Windows executables
|
||||
Windows executables for mainline and stable releases can be found on the main [NGINX download page](https://nginx.org/en/download.html). Note that the current implementation of NGINX for Windows is at the Proof-of-Concept stage and should only be used for development and testing purposes. For additional information, please see [nginx for Windows](https://nginx.org/en/docs/windows.html).
|
||||
|
||||
## Dynamic modules
|
||||
NGINX version 1.9.11 added support for [Dynamic Modules](https://nginx.org/en/docs/ngx_core_module.html#load_module). Unlike Static modules, dynamically built modules can be downloaded, installed, and configured after the core NGINX binaries have been built. [Official dynamic module binaries](https://nginx.org/en/linux_packages.html#dynmodules) are available from the same package repository as the core NGINX binaries described in previous steps.
|
||||
|
||||
> [!TIP]
|
||||
> [NGINX JavaScript (njs)](https://github.com/nginx/njs), is a popular NGINX dynamic module that enables the extension of core NGINX functionality using familiar JavaScript syntax.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If desired, dynamic modules can also be built statically into NGINX at compile time.
|
||||
|
||||
# Getting started with NGINX
|
||||
For a gentle introduction to NGINX basics, please see our [Beginner’s Guide](https://nginx.org/en/docs/beginners_guide.html).
|
||||
|
||||
## Installing SSL certificates and enabling TLS encryption
|
||||
See [Configuring HTTPS servers](https://nginx.org/en/docs/http/configuring_https_servers.html) for a quick guide on how to enable secure traffic to your NGINX installation.
|
||||
|
||||
## Load Balancing
|
||||
For a quick start guide on configuring NGINX as a Load Balancer, please see [Using nginx as HTTP load balancer](https://nginx.org/en/docs/http/load_balancing.html).
|
||||
|
||||
## Rate limiting
|
||||
See our [Rate Limiting with NGINX](https://blog.nginx.org/blog/rate-limiting-nginx) blog post for an overview of core concepts for provisioning NGINX as an API Gateway.
|
||||
|
||||
## Content caching
|
||||
See [A Guide to Caching with NGINX and NGINX Plus](https://blog.nginx.org/blog/nginx-caching-guide) blog post for an overview of how to use NGINX as a content cache (e.g. edge server of a content delivery network).
|
||||
|
||||
# Building from source
|
||||
The following steps can be used to build NGINX from source code available in this repository.
|
||||
|
||||
## Installing dependencies
|
||||
Most Linux distributions will require several dependencies to be installed in order to build NGINX. The following instructions are specific to the `apt` package manager, widely available on most Ubuntu/Debian distributions and their derivatives.
|
||||
|
||||
> [!TIP]
|
||||
> It is always a good idea to update your package repository lists prior to installing new packages.
|
||||
> ```bash
|
||||
> sudo apt update
|
||||
> ```
|
||||
|
||||
### Installing compiler and make utility
|
||||
Use the following command to install the GNU C compiler and Make utility.
|
||||
|
||||
```bash
|
||||
sudo apt install gcc make
|
||||
```
|
||||
|
||||
### Installing dependency libraries
|
||||
|
||||
```bash
|
||||
sudo apt install libpcre3-dev zlib1g-dev
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> This is the minimal set of dependency libraries needed to build NGINX with rewriting and gzip capabilities. Other dependencies may be required if you choose to build NGINX with additional modules. Monitor the output of the `configure` command discussed in the following sections for information on which modules may be missing. For example, if you plan to use SSL certificates to encrypt traffic with TLS, you'll need to install the OpenSSL library. To do so, issue the following command.
|
||||
|
||||
>```bash
|
||||
>sudo apt install libssl-dev
|
||||
|
||||
## Cloning the NGINX GitHub repository
|
||||
Using your preferred method, clone the NGINX repository into your development directory. See [Cloning a GitHub Repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) for additional help.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nginx/nginx.git
|
||||
```
|
||||
|
||||
## Configuring the build
|
||||
Prior to building NGINX, you must run the `configure` script with [appropriate flags](https://nginx.org/en/docs/configure.html). This will generate a Makefile in your NGINX source root directory that can then be used to compile NGINX with [options specified during configuration](https://nginx.org/en/docs/configure.html).
|
||||
|
||||
From the NGINX source code repository's root directory:
|
||||
|
||||
```bash
|
||||
auto/configure
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Configuring the build without any flags will compile NGINX with the default set of options. Please refer to https://nginx.org/en/docs/configure.html for a full list of available build configuration options.
|
||||
|
||||
## Compiling
|
||||
The `configure` script will generate a `Makefile` in the NGINX source root directory upon successful execution. To compile NGINX into a binary, issue the following command from that same directory:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## Location of binary and installation
|
||||
After successful compilation, a binary will be generated at `<NGINX_SRC_ROOT_DIR>/objs/nginx`. To install this binary, issue the following command from the source root directory:
|
||||
|
||||
```bash
|
||||
sudo make install
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The binary will be installed into the `/usr/local/nginx/` directory.
|
||||
|
||||
## Running and testing the installed binary
|
||||
To run the installed binary, issue the following command:
|
||||
|
||||
```bash
|
||||
sudo /usr/local/nginx/sbin/nginx
|
||||
```
|
||||
|
||||
You may test NGINX operation using `curl`.
|
||||
|
||||
```bash
|
||||
curl localhost
|
||||
```
|
||||
|
||||
The output of which should start with:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to nginx!</title>
|
||||
```
|
||||
|
||||
# Asking questions and reporting issues
|
||||
We encourage you to engage with us.
|
||||
- [NGINX GitHub Discussions](https://github.com/nginx/nginx/discussions), is the go-to place to start asking questions and sharing your thoughts.
|
||||
- Our [GitHub Issues](https://github.com/nginx/nginx/issues) page offers space to submit and discuss specific issues, report bugs, and suggest enhancements.
|
||||
|
||||
# Contributing code
|
||||
Please see the [Contributing](CONTRIBUTING.md) guide for information on how to contribute code.
|
||||
|
||||
# Additional help and resources
|
||||
- See the [NGINX Community Blog](https://blog.nginx.org/) for more tips, tricks and HOW-TOs related to NGINX and related projects.
|
||||
- Access [nginx.org](https://nginx.org/), your go-to source for all documentation, information and software related to the NGINX suite of projects.
|
||||
|
||||
# Changelog
|
||||
See our [changelog](https://nginx.org/en/CHANGES) to keep track of updates.
|
||||
|
||||
# License
|
||||
[2-clause BSD-like license](LICENSE)
|
||||
|
||||
---
|
||||
Additional documentation available at: https://nginx.org/en/docs
|
103
nginx-1.28.0/docs/SECURITY.md
Normal file
103
nginx-1.28.0/docs/SECURITY.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Security Policy
|
||||
|
||||
This document provides an overview of security concerns related to nginx
|
||||
deployments, focusing on confidentiality, integrity, availability, and the
|
||||
implications of configurations and misconfigurations.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report any vulnerabilities via one of the following methods
|
||||
(in order of preference):
|
||||
|
||||
1. [Report a vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability)
|
||||
within this repository. We are using the GitHub workflow that allows us to
|
||||
manage vulnerabilities in a private manner and interact with reporters
|
||||
securely.
|
||||
|
||||
2. [Report directly to F5](https://www.f5.com/services/support/report-a-vulnerability).
|
||||
|
||||
3. Report via email to security-alert@nginx.org.
|
||||
This method will be deprecated in the future.
|
||||
|
||||
### Vulnerability Disclosure and Fix Process
|
||||
|
||||
The nginx team expects that all suspected vulnerabilities be reported
|
||||
privately via the
|
||||
[Reporting a Vulnerability](SECURITY.md#reporting-a-vulnerability) guidelines.
|
||||
If a publicly released vulnerability is reported, we
|
||||
may request to handle it according to the private disclosure process.
|
||||
If the reporter agrees, we will follow the private disclosure process.
|
||||
|
||||
Security fixes will be applied to all supported stable releases, as well
|
||||
as the mainline version, as applicable. We recommend using the most recent
|
||||
mainline or stable release of nginx. Fixes are created and tested by the core
|
||||
team using a GitHub private fork for security. If necessary, the reporter
|
||||
may be invited to contribute to the fork and assist with the solution.
|
||||
|
||||
The nginx team is committed to responsible information disclosure with
|
||||
sufficient detail, such as the CVSS score and vector. Privately disclosed
|
||||
vulnerabilities are embargoed by default until the fix is released.
|
||||
Communications and fixes remain private until made public. As nginx is
|
||||
supported by F5, we generally follow the
|
||||
[F5 security vulnerability response policy](https://my.f5.com/manage/s/article/K4602).
|
||||
|
||||
### Vulnerability Disclosure and Fix Service Level Objectives
|
||||
|
||||
- We will acknowledge all vulnerability reports within 1 to 3 days.
|
||||
- Fixes will be developed and released within 90 days from the date of
|
||||
disclosure. If an extension is needed, we will work with the disclosing person.
|
||||
- Publicly disclosed (i.e., Zero-Day vulnerabilities) will be addressed ASAP.
|
||||
|
||||
## Confidentiality, Integrity, and Availability
|
||||
|
||||
### Confidentiality and Integrity
|
||||
|
||||
Vulnerabilities compromising data confidentiality or integrity are considered
|
||||
the highest priority. Any issue leading to unauthorized data access, leaks, or
|
||||
manipulation will trigger the security release process.
|
||||
|
||||
### Availability
|
||||
|
||||
Availability issues must meet the following criteria to trigger the security
|
||||
release process:
|
||||
- Is present in a standard module included with nginx.
|
||||
- Arises from traffic that the module is designed to handle.
|
||||
- Resource exhaustion issues are not mitigated by existing timeout, rate
|
||||
limiting, or buffer size configurations, or applying changes is impractical.
|
||||
- Results in highly asymmetric, extreme resource consumption.
|
||||
|
||||
Availability issues excluded from the security release process:
|
||||
- Local file content or upstream response content resulting only in worker
|
||||
process termination.
|
||||
- Issues with experimental features which result only in availability impact.
|
||||
|
||||
## Trusted Configurations and Misconfigurations
|
||||
|
||||
In nginx, configuration files, modules, certificate/key pairs, nginx JavaScript,
|
||||
and local file content are considered trusted sources. Issues arising from
|
||||
loading or execution of these trusted components are not considered
|
||||
vulnerabilities. Operators are responsible for securing and maintaining the
|
||||
integrity of these sources. Misconfigurations can create vulnerabilities, and
|
||||
operators should implement configurations according to best practices, review
|
||||
them regularly, and apply security updates.
|
||||
|
||||
## Data Plane vs. Control Plane
|
||||
|
||||
The data plane handles traffic through nginx, directly interacting with user
|
||||
data. nginx inherently trusts the content and instructions from upstream
|
||||
servers. The control plane governs configuration, management, and orchestration.
|
||||
Misconfigurations or vulnerabilities in the control plane can cause improper
|
||||
behavior in the data plane.
|
||||
|
||||
## Modules Under Scope
|
||||
|
||||
The policy applies to all nginx modules included in this repository. Security
|
||||
considerations and attack vectors for each module will be identified, with
|
||||
recommended configurations to mitigate risks.
|
||||
|
||||
## Debug Logging and Core Files
|
||||
|
||||
Debug logs and core files produced by nginx may contain un-sanitized data,
|
||||
including sensitive information like client requests, server configurations,
|
||||
and private key material. These artifacts must be handled carefully to avoid
|
||||
exposing confidential data.
|
20
nginx-1.28.0/docs/zlib.LICENSE
Normal file
20
nginx-1.28.0/docs/zlib.LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
(C) 1995-2024 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
19
nginx-1.28.0/html/50x.html
Normal file
19
nginx-1.28.0/html/50x.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Error</title>
|
||||
<style>
|
||||
html { color-scheme: light dark; }
|
||||
body { width: 35em; margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>An error occurred.</h1>
|
||||
<p>Sorry, the page you are looking for is currently unavailable.<br/>
|
||||
Please try again later.</p>
|
||||
<p>If you are the system administrator of this resource then you should check
|
||||
the error log for details.</p>
|
||||
<p><em>Faithfully yours, nginx.</em></p>
|
||||
</body>
|
||||
</html>
|
23
nginx-1.28.0/html/index.html
Normal file
23
nginx-1.28.0/html/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to nginx!</title>
|
||||
<style>
|
||||
html { color-scheme: light dark; }
|
||||
body { width: 35em; margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to nginx!</h1>
|
||||
<p>If you see this page, the nginx web server is successfully installed and
|
||||
working. Further configuration is required.</p>
|
||||
|
||||
<p>For online documentation and support please refer to
|
||||
<a href="http://nginx.org/">nginx.org</a>.<br/>
|
||||
Commercial support is available at
|
||||
<a href="http://nginx.com/">nginx.com</a>.</p>
|
||||
|
||||
<p><em>Thank you for using nginx.</em></p>
|
||||
</body>
|
||||
</html>
|
BIN
nginx-1.28.0/nginx.exe
Normal file
BIN
nginx-1.28.0/nginx.exe
Normal file
Binary file not shown.
@@ -2,8 +2,10 @@ package com.bio.bio_backend;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableJpaAuditing
|
||||
public class BioBackendApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@@ -1,34 +0,0 @@
|
||||
package com.bio.bio_backend.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.bio.bio_backend.entity.Test;
|
||||
import com.bio.bio_backend.repository.TestRepository;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/test")
|
||||
public class TestController {
|
||||
|
||||
private final TestRepository repository;
|
||||
|
||||
public TestController(TestRepository repository){
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Test> getAllUsers(){
|
||||
System.out.println("test10099!!");
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public Test creatTest(@RequestBody Test test){
|
||||
return repository.save(test);
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
package com.bio.bio_backend.domain.user.member.controller;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
|
||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||
import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class MemberController {
|
||||
|
||||
private final MemberService memberService;
|
||||
private final MemberMapper memberMapper;
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
|
||||
@PostMapping("/members")
|
||||
public ResponseEntity<CreateMemberResponseDto> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
|
||||
MemberDto member = memberMapper.toMemberDto(requestDto);
|
||||
MemberDto createdMember = memberService.createMember(member);
|
||||
CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
|
||||
}
|
||||
|
||||
// @PostMapping("/member/list")
|
||||
// public ResponseEntity<List<ResponseMember>> getMemberList(@RequestBody(required = false) Map<String, String> params) {
|
||||
|
||||
// if(params == null){
|
||||
// params = new HashMap<>();
|
||||
// }
|
||||
|
||||
// Iterable<MemberDTO> memberList = memberService.selectMemberList(params);
|
||||
|
||||
// List<ResponseMember> result = new ArrayList<>();
|
||||
|
||||
// memberList.forEach(m -> {
|
||||
// result.add(new ModelMapper().map(m, ResponseMember.class));
|
||||
// });
|
||||
|
||||
// return ResponseEntity.status(HttpStatus.OK).body(result);
|
||||
// }
|
||||
|
||||
// @GetMapping("/member/{seq}")
|
||||
// public ResponseEntity<ResponseMember> selectMember(@PathVariable("seq") int seq) {
|
||||
|
||||
// MemberDTO member = memberService.selectMember(seq);
|
||||
|
||||
// ResponseMember responseMember = mapper.map(member, ResponseMember.class);
|
||||
|
||||
// return ResponseEntity.status(HttpStatus.OK).body(responseMember);
|
||||
// }
|
||||
|
||||
// @PutMapping("/member")
|
||||
// public CustomApiResponse<Void> updateMember(@RequestBody @Valid CreateMemberRequestDTO requestMember, @AuthenticationPrincipal MemberDTO registrant) {
|
||||
// // 현재 JWT는 사용자 id 값을 통하여 생성, 회원정보 변경 시 JWT 재발급 여부 검토
|
||||
|
||||
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
||||
|
||||
// if (requestMember.getPassword() != null) {
|
||||
// member.setPw(bCryptPasswordEncoder.encode(requestMember.getPassword()));
|
||||
// }
|
||||
|
||||
// member.setRegSeq(registrant.getSeq());
|
||||
// memberService.updateMember(member);
|
||||
|
||||
// return CustomApiResponse.success(ApiResponseCode.USER_INFO_CHANGE, null);
|
||||
// }
|
||||
|
||||
// @DeleteMapping("/member")
|
||||
// public CustomApiResponse<Void> deleteMember(@RequestBody @Valid CreateMemberRequestDTO requestMember){
|
||||
|
||||
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
||||
|
||||
// memberService.deleteMember(member);
|
||||
|
||||
// return CustomApiResponse.success(ApiResponseCode.USER_DELETE_SUCCESSFUL, null);
|
||||
// }
|
||||
|
||||
// @PostMapping("/logout")
|
||||
// public CustomApiResponse<Void> logout(@AuthenticationPrincipal MemberDTO member) {
|
||||
|
||||
// String id = member.getId();
|
||||
|
||||
// try {
|
||||
// memberService.deleteRefreshToken(id);
|
||||
// } catch (Exception e) {
|
||||
// return CustomApiResponse.fail(ApiResponseCode.INTERNAL_SERVER_ERROR, null);
|
||||
// }
|
||||
|
||||
// return CustomApiResponse.success(ApiResponseCode.LOGOUT_SUCCESSFUL, null);
|
||||
// }
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.bio.bio_backend.domain.user.member.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CreateMemberRequestDto {
|
||||
|
||||
@NotBlank(message = "아이디는 필수입니다.")
|
||||
private String userId;
|
||||
|
||||
@NotBlank(message = "비밀번호는 필수입니다.")
|
||||
private String password;
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.bio.bio_backend.domain.user.member.dto;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CreateMemberResponseDto {
|
||||
|
||||
private Long oid;
|
||||
private String userId;
|
||||
private MemberRole role;
|
||||
private Boolean useFlag;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.bio.bio_backend.domain.user.member.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class LoginRequestDto {
|
||||
|
||||
@NotBlank(message = "아이디는 필수입니다.")
|
||||
private String userId;
|
||||
|
||||
@NotBlank(message = "비밀번호는 필수입니다.")
|
||||
private String password;
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.bio.bio_backend.domain.user.member.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class LoginResponseDto {
|
||||
|
||||
private String userId;
|
||||
private String role;
|
||||
private LocalDateTime lastLoginAt;
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
package com.bio.bio_backend.domain.user.member.dto;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MemberDto implements UserDetails {
|
||||
|
||||
private Long oid;
|
||||
private String userId;
|
||||
private String password;
|
||||
private MemberRole role;
|
||||
private Boolean useFlag;
|
||||
private String refreshToken;
|
||||
private LocalDateTime lastLoginAt;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + this.role.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return this.useFlag != null && this.useFlag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.useFlag != null && this.useFlag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package com.bio.bio_backend.domain.user.member.entity;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import com.bio.bio_backend.global.entity.BaseEntity;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Getter @Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Table(
|
||||
name = "st_member",
|
||||
indexes = {
|
||||
@Index(name = "idx_member_user_id", columnList = "user_id")
|
||||
}
|
||||
)
|
||||
public class Member extends BaseEntity {
|
||||
|
||||
@Column(name = "user_id", nullable = false, length = 100)
|
||||
private String userId;
|
||||
|
||||
@Column(name = "password", nullable = false, length = 100)
|
||||
private String password;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "role", nullable = false, length = 40)
|
||||
private MemberRole role;
|
||||
|
||||
@Column(name = "use_flag", nullable = false)
|
||||
@Builder.Default
|
||||
private Boolean useFlag = true;
|
||||
|
||||
@Column(name = "refresh_token", length = 200)
|
||||
private String refreshToken;
|
||||
|
||||
@Column(name = "last_login_at")
|
||||
private LocalDateTime lastLoginAt;
|
||||
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package com.bio.bio_backend.domain.user.member.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 회원 역할을 정의하는 Enum
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum MemberRole {
|
||||
|
||||
MEMBER("MEMBER", "일반 회원"),
|
||||
ADMIN("ADMIN", "관리자"),
|
||||
USER("USER", "사용자"),
|
||||
SYSTEM_ADMIN("SYSTEM_ADMIN", "시스템 관리자");
|
||||
|
||||
private final String value;
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* 문자열 값으로부터 MemberRole을 찾는 메서드
|
||||
*/
|
||||
public static MemberRole fromValue(String value) {
|
||||
for (MemberRole role : values()) {
|
||||
if (role.value.equals(value)) {
|
||||
return role;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown MemberRole value: " + value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 기본 역할 반환
|
||||
*/
|
||||
public static MemberRole getDefault() {
|
||||
return MEMBER;
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.bio.bio_backend.domain.user.member.exception;
|
||||
|
||||
public class UserDuplicateException extends RuntimeException {
|
||||
|
||||
public UserDuplicateException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UserDuplicateException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package com.bio.bio_backend.domain.user.member.mapper;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||
import com.bio.bio_backend.domain.user.member.entity.Member;
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MemberMapper {
|
||||
|
||||
MemberMapper INSTANCE = Mappers.getMapper(MemberMapper.class);
|
||||
|
||||
/**
|
||||
* CreateMemberRequestDto를 MemberDto로 변환
|
||||
* 기본값 설정: role = MemberRole.MEMBER, useFlag = true
|
||||
*/
|
||||
@Mapping(target = "oid", ignore = true)
|
||||
@Mapping(target = "role", expression = "java(com.bio.bio_backend.domain.user.member.enums.MemberRole.getDefault())")
|
||||
@Mapping(target = "useFlag", constant = "true")
|
||||
@Mapping(target = "refreshToken", ignore = true)
|
||||
@Mapping(target = "lastLoginAt", ignore = true)
|
||||
@Mapping(target = "createdAt", ignore = true)
|
||||
@Mapping(target = "updatedAt", ignore = true)
|
||||
MemberDto toMemberDto(CreateMemberRequestDto requestDto);
|
||||
|
||||
/**
|
||||
* Member 엔티티를 MemberDto로 변환
|
||||
*/
|
||||
MemberDto toMemberDto(Member member);
|
||||
|
||||
/**
|
||||
* MemberDto를 Member 엔티티로 변환
|
||||
*/
|
||||
Member toMember(MemberDto memberDto);
|
||||
|
||||
/**
|
||||
* Member 엔티티 리스트를 MemberDto 리스트로 변환
|
||||
*/
|
||||
List<MemberDto> toMemberDtoList(List<Member> members);
|
||||
|
||||
/**
|
||||
* MemberDto를 CreateMemberResponseDto로 변환
|
||||
*/
|
||||
CreateMemberResponseDto toCreateMemberResponseDto(MemberDto memberDto);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package com.bio.bio_backend.domain.user.member.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.entity.Member;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface MemberRepository extends JpaRepository<Member, Long> {
|
||||
|
||||
// 사용자 ID로 회원 조회 (Optional 반환)
|
||||
Optional<Member> findByUserId(String userId);
|
||||
|
||||
// 사용자 ID 존재 여부 확인
|
||||
boolean existsByUserId(String userId);
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
package com.bio.bio_backend.domain.user.member.repository;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.entity.Member;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* QueryDSL을 활용한 커스텀 쿼리 메서드들을 정의하는 인터페이스
|
||||
* 복잡한 쿼리나 동적 쿼리가 필요한 경우 이 인터페이스를 구현하여 사용합니다.
|
||||
*/
|
||||
public interface MemberRepositoryCustom {
|
||||
|
||||
/**
|
||||
* 사용자 ID로 회원을 조회합니다.
|
||||
* QueryDSL을 사용하여 더 유연한 쿼리 작성이 가능합니다.
|
||||
*
|
||||
* @param userId 사용자 ID
|
||||
* @return Optional<Member> 회원 정보 (없으면 empty)
|
||||
*/
|
||||
Optional<Member> findByUserIdCustom(String userId);
|
||||
|
||||
/**
|
||||
* 역할(Role)별로 회원 목록을 조회합니다.
|
||||
*
|
||||
* @param role 회원 역할
|
||||
* @return List<Member> 해당 역할을 가진 회원 목록
|
||||
*/
|
||||
List<Member> findByRole(String role);
|
||||
|
||||
/**
|
||||
* 사용 여부별로 회원 목록을 조회합니다.
|
||||
*
|
||||
* @param useFlag 사용 여부
|
||||
* @return List<Member> 해당 사용 여부를 가진 회원 목록
|
||||
*/
|
||||
List<Member> findByUseFlag(Boolean useFlag);
|
||||
|
||||
/**
|
||||
* 사용자 ID와 사용 여부로 회원을 조회합니다.
|
||||
*
|
||||
* @param userId 사용자 ID
|
||||
* @param useFlag 사용 여부
|
||||
* @return Optional<Member> 회원 정보
|
||||
*/
|
||||
Optional<Member> findByUserIdAndUseFlag(String userId, Boolean useFlag);
|
||||
|
||||
/**
|
||||
* 검색 조건에 따른 회원 목록을 페이징하여 조회합니다.
|
||||
*
|
||||
* @param userId 사용자 ID (부분 검색)
|
||||
* @param role 회원 역할
|
||||
* @param useFlag 사용 여부
|
||||
* @param pageable 페이징 정보
|
||||
* @return Page<Member> 페이징된 회원 목록
|
||||
*/
|
||||
Page<Member> findMembersByCondition(String userId, String role, Boolean useFlag, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 마지막 로그인 시간이 특정 시간 이후인 회원들을 조회합니다.
|
||||
*
|
||||
* @param lastLoginAfter 마지막 로그인 기준 시간
|
||||
* @return List<Member> 해당 조건을 만족하는 회원 목록
|
||||
*/
|
||||
List<Member> findActiveMembersByLastLogin(java.time.LocalDateTime lastLoginAfter);
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
package com.bio.bio_backend.domain.user.member.repository;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.entity.Member;
|
||||
import com.bio.bio_backend.domain.user.member.entity.QMember;
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* QueryDSL을 활용하여 MemberRepositoryCustom 인터페이스를 구현하는 클래스
|
||||
* 복잡한 쿼리나 동적 쿼리를 QueryDSL로 작성하여 성능과 가독성을 향상시킵니다.
|
||||
*/
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class MemberRepositoryImpl implements MemberRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory queryFactory;
|
||||
|
||||
/**
|
||||
* QMember 인스턴스를 생성하여 쿼리에서 사용합니다.
|
||||
* QueryDSL의 Q클래스를 통해 타입 안전한 쿼리 작성이 가능합니다.
|
||||
*/
|
||||
private final QMember member = QMember.member;
|
||||
|
||||
@Override
|
||||
public Optional<Member> findByUserIdCustom(String userId) {
|
||||
// QueryDSL을 사용하여 사용자 ID로 회원을 조회합니다.
|
||||
// eq() 메서드를 사용하여 정확한 일치 조건을 설정합니다.
|
||||
Member foundMember = queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.userId.eq(userId))
|
||||
.fetchOne();
|
||||
|
||||
return Optional.ofNullable(foundMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Member> findByRole(String role) {
|
||||
// 역할별로 회원을 조회합니다.
|
||||
// String을 MemberRole enum으로 변환하여 비교합니다.
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.role.eq(MemberRole.fromValue(role)))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Member> findByUseFlag(Boolean useFlag) {
|
||||
// 사용 여부별로 회원을 조회합니다.
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.useFlag.eq(useFlag))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Member> findByUserIdAndUseFlag(String userId, Boolean useFlag) {
|
||||
// 사용자 ID와 사용 여부를 모두 만족하는 회원을 조회합니다.
|
||||
// and() 메서드를 사용하여 여러 조건을 결합합니다.
|
||||
Member foundMember = queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.userId.eq(userId)
|
||||
.and(member.useFlag.eq(useFlag)))
|
||||
.fetchOne();
|
||||
|
||||
return Optional.ofNullable(foundMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Member> findMembersByCondition(String userId, String role, Boolean useFlag, Pageable pageable) {
|
||||
// BooleanBuilder를 사용하여 동적 쿼리를 구성합니다.
|
||||
// null이 아닌 조건만 쿼리에 포함시킵니다.
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
// 사용자 ID가 제공된 경우 부분 검색 조건을 추가합니다.
|
||||
if (userId != null && !userId.trim().isEmpty()) {
|
||||
builder.and(member.userId.containsIgnoreCase(userId));
|
||||
}
|
||||
|
||||
// 역할이 제공된 경우 정확한 일치 조건을 추가합니다.
|
||||
if (role != null && !role.trim().isEmpty()) {
|
||||
builder.and(member.role.eq(MemberRole.fromValue(role)));
|
||||
}
|
||||
|
||||
// 사용 여부가 제공된 경우 정확한 일치 조건을 추가합니다.
|
||||
if (useFlag != null) {
|
||||
builder.and(member.useFlag.eq(useFlag));
|
||||
}
|
||||
|
||||
// 전체 개수를 조회합니다.
|
||||
long total = queryFactory
|
||||
.selectFrom(member)
|
||||
.where(builder)
|
||||
.fetchCount();
|
||||
|
||||
// 페이징 조건을 적용하여 결과를 조회합니다.
|
||||
List<Member> content = queryFactory
|
||||
.selectFrom(member)
|
||||
.where(builder)
|
||||
.orderBy(member.createdAt.desc()) // 생성일 기준 내림차순 정렬
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// Page 객체를 생성하여 반환합니다.
|
||||
return new PageImpl<>(content, pageable, total);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Member> findActiveMembersByLastLogin(LocalDateTime lastLoginAfter) {
|
||||
// 마지막 로그인 시간이 특정 시간 이후인 활성 회원들을 조회합니다.
|
||||
// 여러 조건을 조합하여 복잡한 쿼리를 작성합니다.
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.useFlag.eq(true) // 사용 중인 상태
|
||||
.and(member.lastLoginAt.isNotNull()) // 마지막 로그인 시간이 존재
|
||||
.and(member.lastLoginAt.after(lastLoginAfter))) // 특정 시간 이후
|
||||
.orderBy(member.lastLoginAt.desc()) // 마지막 로그인 시간 기준 내림차순 정렬
|
||||
.fetch();
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.bio.bio_backend.domain.user.member.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||
|
||||
public interface MemberService extends UserDetailsService {
|
||||
|
||||
UserDetails loadUserByUsername(String id);
|
||||
|
||||
MemberDto createMember(MemberDto memberDTO);
|
||||
|
||||
void updateRefreshToken(MemberDto memberDTO);
|
||||
|
||||
String getRefreshToken(String id);
|
||||
|
||||
int deleteRefreshToken(String id);
|
||||
|
||||
List<MemberDto> selectMemberList(Map<String, String> params);
|
||||
|
||||
MemberDto selectMember(long seq);
|
||||
|
||||
int updateMember(MemberDto member);
|
||||
|
||||
int deleteMember(MemberDto member);
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
package com.bio.bio_backend.domain.user.member.service;
|
||||
|
||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||
import com.bio.bio_backend.domain.user.member.entity.Member;
|
||||
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
|
||||
import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
|
||||
import com.bio.bio_backend.domain.user.member.repository.MemberRepository;
|
||||
import com.bio.bio_backend.domain.user.member.exception.UserDuplicateException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.bio.bio_backend.global.utils.OidUtil.generateOid;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Transactional(readOnly = true)
|
||||
public class MemberServiceImpl implements MemberService {
|
||||
|
||||
private final MemberMapper memberMapper; // MapStruct Mapper 사용
|
||||
private final MemberRepository memberRepository;
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
|
||||
// JPA 레파지토리를 사용하여 회원 조회
|
||||
Member member = memberRepository.findByUserId(id)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found with id : " + id));
|
||||
|
||||
// MapStruct를 사용하여 Member 엔티티를 MemberDto로 변환
|
||||
MemberDto memberDto = memberMapper.toMemberDto(member);
|
||||
|
||||
return memberDto;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public MemberDto createMember(MemberDto memberDTO) {
|
||||
// userId 중복 체크
|
||||
if (memberRepository.existsByUserId(memberDTO.getUserId())) {
|
||||
throw new UserDuplicateException("User ID already exists");
|
||||
}
|
||||
|
||||
Member member = Member.builder()
|
||||
.userId(memberDTO.getUserId())
|
||||
.password(bCryptPasswordEncoder.encode(memberDTO.getPassword()))
|
||||
.role(MemberRole.getDefault())
|
||||
.build();
|
||||
|
||||
Long oid = generateOid();
|
||||
member.setOid(oid);
|
||||
member.setCreatedOid(oid);
|
||||
|
||||
Member savedMember = memberRepository.save(member);
|
||||
|
||||
return memberMapper.toMemberDto(savedMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateRefreshToken(MemberDto memberDTO) {
|
||||
// JPA를 사용하여 refresh token 업데이트
|
||||
Member member = memberRepository.findByUserId(memberDTO.getUserId())
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDTO.getUserId()));
|
||||
|
||||
member.setRefreshToken(memberDTO.getRefreshToken());
|
||||
memberRepository.save(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefreshToken(String id) {
|
||||
Member member = memberRepository.findByUserId(id)
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + id));
|
||||
|
||||
return member.getRefreshToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteRefreshToken(String id) {
|
||||
Member member = memberRepository.findByUserId(id)
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + id));
|
||||
|
||||
member.setRefreshToken(null);
|
||||
memberRepository.save(member);
|
||||
return 1; // 성공 시 1 반환
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberDto> selectMemberList(Map<String, String> params) {
|
||||
// JPA를 사용하여 회원 목록 조회 (간단한 구현)
|
||||
List<Member> members = memberRepository.findAll();
|
||||
|
||||
// MapStruct를 사용하여 Member 엔티티 리스트를 MemberDto 리스트로 변환
|
||||
return memberMapper.toMemberDtoList(members);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberDto selectMember(long seq) {
|
||||
// JPA 레파지토리를 사용하여 회원 조회
|
||||
Member member = memberRepository.findById(seq)
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. seq: " + seq));
|
||||
|
||||
// MapStruct를 사용하여 Member 엔티티를 MemberDto로 자동 변환
|
||||
return memberMapper.toMemberDto(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int updateMember(MemberDto memberDto) {
|
||||
Member member = memberRepository.findByUserId(memberDto.getUserId())
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDto.getUserId()));
|
||||
|
||||
// 비밀번호가 변경된 경우 암호화
|
||||
if (memberDto.getPassword() != null && !memberDto.getPassword().isEmpty()) {
|
||||
member.setPassword(bCryptPasswordEncoder.encode(memberDto.getPassword()));
|
||||
}
|
||||
|
||||
member.setRole(memberDto.getRole());
|
||||
member.setUseFlag(memberDto.getUseFlag());
|
||||
|
||||
memberRepository.save(member);
|
||||
return 1; // 성공 시 1 반환
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteMember(MemberDto memberDto) {
|
||||
Member member = memberRepository.findByUserId(memberDto.getUserId())
|
||||
.orElseThrow(() -> new RuntimeException("회원을 찾을 수 없습니다. id: " + memberDto.getUserId()));
|
||||
|
||||
member.setUseFlag(false);
|
||||
|
||||
log.info("회원 삭제 처리: {}", member.toString());
|
||||
|
||||
memberRepository.save(member);
|
||||
return 1; // 성공 시 1 반환
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package com.bio.bio_backend.entity;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Test {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
private String email;
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.bio.bio_backend.global.aop;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RepositoryLoggingAspect {
|
||||
|
||||
/**
|
||||
* Repository 계층의 모든 메서드 호출을 가로채서 로깅하는 Around 어드바이스
|
||||
*/
|
||||
@Around("execution(* org.springframework.data.repository.Repository+.*(..))")
|
||||
public Object logQueryCall(ProceedingJoinPoint pjp) throws Throwable {
|
||||
// 메서드 실행 시작 시간을 기록
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
// 실행될 메서드의 클래스명과 메서드명을 추출
|
||||
String type = pjp.getSignature().getDeclaringTypeName();
|
||||
String method = pjp.getSignature().getName();
|
||||
|
||||
// 메서드 호출 시 전달되는 매개변수들을 추출
|
||||
Object[] args = pjp.getArgs();
|
||||
|
||||
// 메서드 호출 시작을 로그로 기록
|
||||
log.info("[QUERY CALL] {}.{}(args={})", type, method, java.util.Arrays.toString(args));
|
||||
|
||||
try {
|
||||
// 원본 메서드를 실행
|
||||
Object result = pjp.proceed();
|
||||
|
||||
// 메서드 실행 완료를 로그로 기록 (실행 시간 포함)
|
||||
log.info("[QUERY DONE] {}.{}() in {}ms", type, method, (System.currentTimeMillis() - t0));
|
||||
|
||||
// 원본 메서드의 결과를 반환
|
||||
return result;
|
||||
} catch (Throwable ex) {
|
||||
log.warn("[QUERY FAIL] {}.{}() -> {}", type, method, ex.toString());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.bio.bio_backend.global.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.bio.bio_backend.global.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOriginPattern("*");
|
||||
config.addAllowedHeader("*");
|
||||
config.addAllowedMethod("*");
|
||||
config.setAllowCredentials(true);
|
||||
|
||||
config.addExposedHeader("Authorization");
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
|
||||
return new CorsFilter(source);
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package com.bio.bio_backend.global.config;
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* QueryDSL 설정을 위한 Configuration 클래스
|
||||
* JPAQueryFactory Bean을 등록하여 QueryDSL을 사용할 수 있도록 합니다.
|
||||
*/
|
||||
@Configuration
|
||||
public class QuerydslConfig {
|
||||
|
||||
/**
|
||||
* JPA EntityManager를 주입받습니다.
|
||||
* @PersistenceContext 어노테이션을 사용하여 Spring이 관리하는 EntityManager를 주입받습니다.
|
||||
*/
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
/**
|
||||
* JPAQueryFactory Bean을 생성하여 등록합니다.
|
||||
* 이 Bean은 QueryDSL을 사용하는 Repository에서 주입받아 사용됩니다.
|
||||
*
|
||||
* @return JPAQueryFactory 인스턴스
|
||||
*/
|
||||
@Bean
|
||||
public JPAQueryFactory jpaQueryFactory() {
|
||||
return new JPAQueryFactory(entityManager);
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package com.bio.bio_backend.global.dto;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
//공통 response Class
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class CustomApiResponse<T> {
|
||||
|
||||
private int code;
|
||||
private String message;
|
||||
private String description;
|
||||
private T data;
|
||||
|
||||
private static final int SUCCESS = 200;
|
||||
|
||||
private CustomApiResponse(int code, String message, String description, T data){
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.description = description;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static <T> CustomApiResponse<T> success(ApiResponseCode responseCode, T data) {
|
||||
return new CustomApiResponse<T>(SUCCESS, responseCode.name(), responseCode.getDescription(), data);
|
||||
}
|
||||
|
||||
public static <T> CustomApiResponse<T> fail(ApiResponseCode responseCode, T data) {
|
||||
return new CustomApiResponse<T>(responseCode.getStatusCode(), responseCode.name(), responseCode.getDescription(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,47 @@
|
||||
package com.bio.bio_backend.global.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.bio.bio_backend.global.utils.OidUtil.generateOid;
|
||||
|
||||
/**
|
||||
* 모든 엔티티가 상속받는 기본 엔티티 클래스
|
||||
* 공통 필드들을 정의하고 JPA Auditing을 지원합니다.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public abstract class BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "oid", nullable = false)
|
||||
private Long oid;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", nullable = false, updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@LastModifiedDate
|
||||
@Column(name = "updated_at", nullable = false)
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Column(name = "created_oid", updatable = false)
|
||||
private Long createdOid;
|
||||
|
||||
@Column(name = "updated_oid")
|
||||
private Long updatedOid;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
if(this.oid == null) this.oid = generateOid();
|
||||
if(this.createdOid != null && this.updatedOid == null) this.updatedOid = this.createdOid;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package com.bio.bio_backend.global.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
//Spring Security login -> filter 수행 -> ExceptionHandler 적용불가로 별도 FailureHandler 를 통하여 Error 응답 처리
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
|
||||
log.info("exception : " + exception.toString());
|
||||
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
|
||||
CustomApiResponse<String> apiResponse;
|
||||
if (exception instanceof UsernameNotFoundException) {
|
||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.USER_NOT_FOUND, null);
|
||||
} else if (exception instanceof BadCredentialsException) {
|
||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.AUTHENTICATION_FAILED, null);
|
||||
} else {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.INTERNAL_SERVER_ERROR, null);
|
||||
}
|
||||
|
||||
String jsonResponse = objectMapper.writeValueAsString(apiResponse);
|
||||
response.getWriter().write(jsonResponse);
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package com.bio.bio_backend.global.exception;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
import io.jsonwebtoken.security.SignatureException;
|
||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
import com.bio.bio_backend.domain.user.member.exception.UserDuplicateException;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public CustomApiResponse<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
|
||||
if (Objects.requireNonNull(e.getMessage()).contains("JSON parse error")) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_FORMAT_WRONG, null);
|
||||
}
|
||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_BAD_REQUEST, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public CustomApiResponse<Void> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_METHOD_NOT_ALLOWED, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoResourceFoundException.class)
|
||||
public CustomApiResponse<Void> handleNoResourceFoundException(NoResourceFoundException e){
|
||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_NOT_FOUND, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public CustomApiResponse<Void> handleIllegalArgumentException(IllegalArgumentException e){
|
||||
return CustomApiResponse.fail(ApiResponseCode.ARGUMENT_NOT_VALID, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IndexOutOfBoundsException.class)
|
||||
public CustomApiResponse<Void> handleIndexOutOfBoundsException(IndexOutOfBoundsException e){
|
||||
return CustomApiResponse.fail(ApiResponseCode.INDEX_OUT_OF_BOUND, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(SignatureException.class)
|
||||
public CustomApiResponse<Void> handleSignatureException(SignatureException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.JWT_SIGNATURE_MISMATCH, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MalformedJwtException.class)
|
||||
public CustomApiResponse<Void> handleMalformedJwtException(MalformedJwtException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.JWT_SIGNATURE_MISMATCH, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(JwtException.class)
|
||||
public CustomApiResponse<Void> handleJwtExceptionException(JwtException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_NULL, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ExpiredJwtException.class)
|
||||
public CustomApiResponse<Void> handleExpiredJwtException(ExpiredJwtException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_EXPIRED, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(JsonProcessingException.class)
|
||||
public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.JSON_PROCESSING_EXCEPTION, null);
|
||||
}
|
||||
|
||||
@ExceptionHandler(UserDuplicateException.class)
|
||||
public CustomApiResponse<Void> handleUserDuplicateException(UserDuplicateException e) {
|
||||
return CustomApiResponse.fail(ApiResponseCode.USER_ID_DUPLICATE, null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package com.bio.bio_backend.global.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
|
||||
@Component
|
||||
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
|
||||
private final HandlerExceptionResolver resolver;
|
||||
|
||||
public JwtAccessDeniedHandler(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
|
||||
Exception exception = (Exception) request.getAttribute("exception");
|
||||
|
||||
if (exception != null) {
|
||||
resolver.resolveException(request, response, null, exception);
|
||||
} else {
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper().writeValue(response.getWriter(),
|
||||
CustomApiResponse.fail(ApiResponseCode.COMMON_FORBIDDEN, null));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.bio.bio_backend.global.exception;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
private final HandlerExceptionResolver resolver;
|
||||
|
||||
public JwtAuthenticationEntryPoint(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
Exception exception = (Exception) request.getAttribute("exception");
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
|
||||
if (exception == null) {
|
||||
return;
|
||||
}
|
||||
resolver.resolveException(request, response, null, exception);
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
//package com.bio.bio_backend.filter;
|
||||
//
|
||||
//import java.io.IOException;
|
||||
//import java.sql.Timestamp;
|
||||
//
|
||||
//import org.springframework.security.core.Authentication;
|
||||
//import org.springframework.security.core.context.SecurityContextHolder;
|
||||
//import org.springframework.web.filter.OncePerRequestFilter;
|
||||
//
|
||||
//import jakarta.servlet.FilterChain;
|
||||
//import jakarta.servlet.ServletException;
|
||||
//import jakarta.servlet.http.HttpServletRequest;
|
||||
//import jakarta.servlet.http.HttpServletResponse;
|
||||
//import com.bio.bio_backend.domain.common.dto.AccessLogDTO;
|
||||
//import com.bio.bio_backend.domain.common.service.AccessLogService;
|
||||
//import com.bio.bio_backend.domain.user.member.dto.MemberDTO;
|
||||
//import com.bio.bio_backend.global.utils.HttpUtils;
|
||||
//
|
||||
//public class HttpLoggingFilter extends OncePerRequestFilter {
|
||||
//
|
||||
//// private AccessLogService accessLogService;
|
||||
// private HttpUtils httpUtils;
|
||||
//
|
||||
// public HttpLoggingFilter(AccessLogService accessLogService, HttpUtils httpUtils) {
|
||||
// this.accessLogService = accessLogService;
|
||||
// this.httpUtils = httpUtils;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
// throws ServletException, IOException {
|
||||
// // Request 요청 시간
|
||||
// Long startedAt = System.currentTimeMillis();
|
||||
// filterChain.doFilter(request, response);
|
||||
// Long finishedAt = System.currentTimeMillis();
|
||||
//
|
||||
// Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
// MemberDTO member = null;
|
||||
// if(auth != null && auth.getPrincipal() instanceof MemberDTO) {
|
||||
// member = (MemberDTO) auth.getPrincipal();
|
||||
// }
|
||||
//
|
||||
// AccessLogDTO log = new AccessLogDTO();
|
||||
// log.setMbrSeq(member == null ? -1 : member.getSeq());
|
||||
// log.setType(httpUtils.getResponseType(response.getContentType()));
|
||||
// log.setMethod(request.getMethod());
|
||||
// log.setIp(httpUtils.getClientIp());
|
||||
// log.setUri(request.getRequestURI());
|
||||
// log.setReqAt(new Timestamp(startedAt));
|
||||
// log.setResAt(new Timestamp(finishedAt));
|
||||
// log.setElapsedTime(finishedAt - startedAt);
|
||||
// log.setResStatus(String.valueOf(response.getStatus()));
|
||||
//
|
||||
// accessLogService.createAccessLog(log);
|
||||
// }
|
||||
//
|
||||
//}
|
@@ -0,0 +1,121 @@
|
||||
package com.bio.bio_backend.global.security;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
||||
import com.bio.bio_backend.domain.user.member.dto.LoginRequestDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.LoginResponseDto;
|
||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final MemberService memberService;
|
||||
private final JwtUtils jwtUtils;
|
||||
private final Environment env;
|
||||
|
||||
// 사용자 login 인증 처리
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException {
|
||||
|
||||
LoginRequestDto requestDto = new ObjectMapper().readValue(request.getInputStream(), LoginRequestDto.class);
|
||||
|
||||
// UsernamePasswordAuthenticationToken authToken;
|
||||
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(requestDto.getUserId(), requestDto.getPassword());
|
||||
|
||||
/*
|
||||
if (req.getLoginLogFlag() == 1) {
|
||||
authToken = new UsernamePasswordAuthenticationToken("admin2", "test123!"); // 비밀번호는 실제 비밀번호로 설정해야 함
|
||||
} else {
|
||||
throw new AuthenticationServiceException("login fail");
|
||||
}
|
||||
*/
|
||||
return authenticationManager.authenticate(authToken);
|
||||
}
|
||||
|
||||
// 사용자 인증 성공 후 token 발급
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain, Authentication authResult) throws IOException, ServletException {
|
||||
|
||||
UserDetails userDetails = (UserDetails) authResult.getPrincipal();
|
||||
|
||||
MemberDto member = (MemberDto) userDetails;
|
||||
|
||||
String accessToken = jwtUtils.generateToken(member.getUserId(), member.getRole().getValue(),
|
||||
Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access"))));
|
||||
|
||||
String refreshToken = jwtUtils.generateToken(member.getUserId(), member.getRole().getValue(),
|
||||
Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_refresh"))));
|
||||
|
||||
|
||||
member.setRefreshToken(refreshToken);
|
||||
member.setLastLoginAt(LocalDateTime.now());
|
||||
|
||||
memberService.updateRefreshToken(member);
|
||||
|
||||
// Refresh 토큰 쿠키 저장
|
||||
Cookie refreshTokenCookie = new Cookie("RefreshToken", refreshToken);
|
||||
refreshTokenCookie.setHttpOnly(true);
|
||||
refreshTokenCookie.setSecure(false);
|
||||
refreshTokenCookie.setPath("/");
|
||||
refreshTokenCookie.setMaxAge(Integer.parseInt(env.getProperty("token.expiration_time_refresh")));
|
||||
|
||||
// JWT 토큰 전달
|
||||
response.setHeader("Authorization", "Bearer " + accessToken);
|
||||
// response.addCookie(refreshTokenCookie);
|
||||
response.addHeader("Set-Cookie",
|
||||
String.format("%s=%s; HttpOnly; Secure; Path=/; Max-Age=%d; SameSite=None",
|
||||
refreshTokenCookie.getName(),
|
||||
refreshTokenCookie.getValue(),
|
||||
refreshTokenCookie.getMaxAge()));
|
||||
|
||||
SecurityContextHolderStrategy contextHolder = SecurityContextHolder.getContextHolderStrategy();
|
||||
SecurityContext context = contextHolder.createEmptyContext();
|
||||
context.setAuthentication(authResult);
|
||||
contextHolder.setContext(context);
|
||||
|
||||
LoginResponseDto memberData = new LoginResponseDto();
|
||||
memberData.setUserId(member.getUserId());
|
||||
memberData.setRole(member.getRole().getValue());
|
||||
memberData.setLastLoginAt(member.getLastLoginAt());
|
||||
|
||||
// login 성공 메시지 전송
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper().writeValue(response.getWriter(),
|
||||
CustomApiResponse.success(ApiResponseCode.LOGIN_SUCCESSFUL, memberData));
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
package com.bio.bio_backend.global.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtUtils jwtUtils;
|
||||
private final MemberService memberService;
|
||||
private final Environment env;
|
||||
|
||||
private final UriAllowFilter uriAllowFilter;
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
|
||||
return uriAllowFilter.authExceptionAllow(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
String accessToken = jwtUtils.extractAccessJwtFromRequest(request);
|
||||
String refreshToken = jwtUtils.extractRefreshJwtFromCookie(request);
|
||||
|
||||
if(accessToken == null){
|
||||
sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_NULL, null));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 토큰 유효성 검사
|
||||
try {
|
||||
if (jwtUtils.validateAccessToken(accessToken)) {
|
||||
String username = jwtUtils.extractUsername(accessToken);
|
||||
UserDetails userDetails = memberService.loadUserByUsername(username);
|
||||
|
||||
if (userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (ExpiredJwtException ignored) {
|
||||
// Access Token이 만료된 경우에만 ignored >> Refresh Token 검증 수행
|
||||
}
|
||||
// Refresh Token 유효성 검사
|
||||
if (refreshToken != null && jwtUtils.validateRefreshToken(refreshToken)) {
|
||||
String username = jwtUtils.extractUsername(refreshToken);
|
||||
String role = (String) jwtUtils.extractAllClaims(refreshToken).get("role");
|
||||
String newAccessToken = jwtUtils.generateToken(username, role,
|
||||
Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access"))));
|
||||
// 새로운 Access Token을 응답 헤더에 설정
|
||||
response.setHeader("Authorization", "Bearer " + newAccessToken);
|
||||
filterChain.doFilter(request, response);
|
||||
} else {
|
||||
sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.All_TOKEN_INVALID, null));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
request.setAttribute("exception", e);
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private void sendJsonResponse(HttpServletResponse response, CustomApiResponse<?> apiResponse) throws IOException {
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setStatus(apiResponse.getCode());
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String jsonResponse = objectMapper.writeValueAsString(apiResponse);
|
||||
response.getWriter().write(jsonResponse);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.bio.bio_backend.global.security;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@Component
|
||||
public class UriAllowFilter {
|
||||
|
||||
@Autowired
|
||||
// ProgramService programService;
|
||||
|
||||
public boolean authExceptionAllow(HttpServletRequest request) {
|
||||
// 임시로 모든 요청 허용
|
||||
return true;
|
||||
|
||||
// String[] allowUrl = programService.getAuthException();
|
||||
// boolean success = Arrays.stream(allowUrl).anyMatch(pattern -> matches(pattern, request.getRequestURI()));
|
||||
// return success;
|
||||
}
|
||||
|
||||
boolean matches(String pattern, String uri) {
|
||||
String regex = pattern.replace("/**", "(/.*)?").replace("*", ".*");
|
||||
return Pattern.matches(regex, uri);
|
||||
}
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
package com.bio.bio_backend.global.security;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
//import com.bio.bio_backend.domain.common.service.AccessLogService;
|
||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||
import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
|
||||
import com.bio.bio_backend.global.exception.JwtAccessDeniedHandler;
|
||||
import com.bio.bio_backend.global.exception.JwtAuthenticationEntryPoint;
|
||||
//import com.bio.bio_backend.global.filter.HttpLoggingFilter;
|
||||
import com.bio.bio_backend.global.utils.HttpUtils;
|
||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class WebSecurity {
|
||||
|
||||
private final MemberService memberService;
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
private final JwtUtils jwtUtils;
|
||||
// private final AccessLogService accessLogService;
|
||||
private final CorsFilter corsFilter;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final HttpUtils httpUtils;
|
||||
private final Environment env;
|
||||
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
||||
|
||||
private final UriAllowFilter uriAllowFilter;
|
||||
|
||||
|
||||
private JwtAuthenticationFilter getJwtAuthenticationFilter(AuthenticationManager authenticationManager) throws Exception {
|
||||
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(authenticationManager, memberService, jwtUtils, env);
|
||||
filter.setFilterProcessesUrl("/login"); // 로그인 EndPoint
|
||||
filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
|
||||
return filter;
|
||||
}
|
||||
|
||||
private Filter getJwtTokenFilter() {
|
||||
return new JwtTokenFilter(jwtUtils, memberService, env, uriAllowFilter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
|
||||
// AuthenticationManager 설정
|
||||
AuthenticationManagerBuilder authenticationManagerBuilder =
|
||||
http.getSharedObject(AuthenticationManagerBuilder.class);
|
||||
authenticationManagerBuilder.userDetailsService(memberService).passwordEncoder(bCryptPasswordEncoder);
|
||||
|
||||
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
|
||||
|
||||
http.csrf(AbstractHttpConfigurer::disable) //csrf 비활성화
|
||||
.authorizeHttpRequests(request -> //request 허용 설정
|
||||
request
|
||||
.anyRequest().permitAll() // 모든 요청 허용
|
||||
// .requestMatchers("/ws/**").permitAll()
|
||||
// .requestMatchers("/admin/**", "/join").hasAnyAuthority(MemberConstants.ROLE_ADMIN)
|
||||
// .requestMatchers("/member/**").hasAnyAuthority(MemberConstants.ROLE_MEMBER)
|
||||
// .anyRequest().authenticated()
|
||||
)
|
||||
.authenticationManager(authenticationManager)
|
||||
.logout(AbstractHttpConfigurer::disable);
|
||||
|
||||
// 예외 처리 핸들링
|
||||
http.exceptionHandling((exceptionConfig) ->
|
||||
exceptionConfig
|
||||
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||
.accessDeniedHandler(jwtAccessDeniedHandler)
|
||||
);
|
||||
|
||||
// http
|
||||
// .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// .addFilterBefore(new HttpLoggingFilter(accessLogService, httpUtils), UsernamePasswordAuthenticationFilter.class)
|
||||
// .addFilterBefore(getJwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class)
|
||||
// .addFilterBefore(getJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
|
||||
// .sessionManagement(httpSecuritySessionManagementConfigurer -> //Session 사용 X
|
||||
// httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package com.bio.bio_backend.global.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/*
|
||||
* API 관련 RESPONSE ENUM
|
||||
*/
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ApiResponseCode {
|
||||
|
||||
/*login & logout*/
|
||||
|
||||
// 200 OK
|
||||
LOGIN_SUCCESSFUL(HttpStatus.OK.value(), "Login successful"),
|
||||
|
||||
LOGOUT_SUCCESSFUL(HttpStatus.OK.value(), "Logout successful"),
|
||||
|
||||
USER_INFO_CHANGE(HttpStatus.OK.value(), "User info update successful"),
|
||||
|
||||
USER_DELETE_SUCCESSFUL(HttpStatus.OK.value(), "User delete is successful"),
|
||||
|
||||
// 401 Unauthorized
|
||||
USER_NOT_FOUND(HttpStatus.UNAUTHORIZED.value(), "User not found. Authentication failed"),
|
||||
|
||||
AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED.value(), "Password is invalid"),
|
||||
|
||||
// 409 Conflict
|
||||
USER_ID_DUPLICATE(HttpStatus.CONFLICT.value(), "User ID already exists"),
|
||||
|
||||
/*auth*/
|
||||
// 401 Unauthorized
|
||||
JWT_SIGNATURE_MISMATCH(HttpStatus.UNAUTHORIZED.value(), "JWT signature does not match. Authentication failed"),
|
||||
|
||||
JWT_TOKEN_NULL(HttpStatus.UNAUTHORIZED.value(), "JWT token is null"),
|
||||
|
||||
JWT_TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED.value(), "Token is Expired"),
|
||||
|
||||
All_TOKEN_INVALID(HttpStatus.UNAUTHORIZED.value(), "Access and Refresh tokens are expired or invalid"),
|
||||
|
||||
/*공통 Code*/
|
||||
// 400 Bad Request
|
||||
COMMON_BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), "Required request body is missing or Error"),
|
||||
|
||||
COMMON_FORMAT_WRONG(HttpStatus.BAD_REQUEST.value(), "Request format is incorrect"),
|
||||
|
||||
// 401 Unauthorized
|
||||
COMMON_UNAUTHORIZED(HttpStatus.UNAUTHORIZED.value(), "Unauthorized"),
|
||||
|
||||
// 403 Forbidden
|
||||
COMMON_FORBIDDEN(HttpStatus.FORBIDDEN.value(), "Access is denied"),
|
||||
|
||||
// 404 Not Found
|
||||
COMMON_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "Resource is not found"),
|
||||
|
||||
// 405 Method Not Allowed
|
||||
COMMON_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED.value(), "Method not Allowed"),
|
||||
|
||||
// 500 Internal Server Error
|
||||
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An error occurred on the server"),
|
||||
|
||||
ARGUMENT_NOT_VALID(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Argument is not valid"),
|
||||
|
||||
INDEX_OUT_OF_BOUND(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Index out of bounds for length"),
|
||||
|
||||
JSON_PROCESSING_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Check if it is a valid JSON format");
|
||||
|
||||
private final int statusCode;
|
||||
private final String description;
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.bio.bio_backend.global.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
||||
import com.bio.bio_backend.global.utils.OidUtil;
|
||||
|
||||
public class CustomIdGenerator implements IdentifierGenerator {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Serializable generate(SharedSessionContractImplementor session, Object object) {
|
||||
return OidUtil.generateOid(); // 재사용
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package com.bio.bio_backend.global.utils;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@Component
|
||||
public class HttpUtils {
|
||||
public String getClientIp() {
|
||||
String ip = "";
|
||||
HttpServletRequest request =
|
||||
((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||
|
||||
ip = request.getHeader("X-Forwarded-For");
|
||||
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-RealIP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("REMOTE_ADDR");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
HttpServletRequest request =
|
||||
((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||
|
||||
return request.getRequestURI();
|
||||
}
|
||||
|
||||
public String getResponseType(String contentType) {
|
||||
if(contentType == null) {
|
||||
return "";
|
||||
} else if(contentType.contains("text/html")) {
|
||||
return "PAGE";
|
||||
} else if (contentType.contains("application/json")) {
|
||||
return "API";
|
||||
};
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
90
src/main/java/com/bio/bio_backend/global/utils/JwtUtils.java
Normal file
90
src/main/java/com/bio/bio_backend/global/utils/JwtUtils.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package com.bio.bio_backend.global.utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtUtils {
|
||||
|
||||
private final MemberService memberService;
|
||||
|
||||
@Value("${token.secret_key}")
|
||||
private String SECRET_KEY;
|
||||
|
||||
private SecretKey getSigningKey() {
|
||||
byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
|
||||
return Keys.hmacShaKeyFor(keyBytes);
|
||||
}
|
||||
|
||||
// Token 생성
|
||||
public String generateToken(String username, String role, long expirationTime) {
|
||||
|
||||
return Jwts.builder()
|
||||
.subject(username)
|
||||
.claim("role", role)
|
||||
.issuedAt(new Date(System.currentTimeMillis()))
|
||||
.expiration(new Date(System.currentTimeMillis() + expirationTime))
|
||||
.signWith(getSigningKey())
|
||||
.compact();
|
||||
}
|
||||
|
||||
// Token 검증
|
||||
public Boolean validateAccessToken(String token) {
|
||||
return isTokenExpired(token);
|
||||
}
|
||||
|
||||
public Boolean validateRefreshToken(String token) {
|
||||
String saveToken = memberService.getRefreshToken(extractUsername(token));
|
||||
return (saveToken.equals(token) && isTokenExpired(token));
|
||||
}
|
||||
|
||||
private boolean isTokenExpired(String token) {
|
||||
return !extractAllClaims(token).getExpiration().before(new Date());
|
||||
}
|
||||
|
||||
public String extractUsername(String token) {
|
||||
return extractAllClaims(token).getSubject();
|
||||
}
|
||||
|
||||
public Claims extractAllClaims(String token) {
|
||||
|
||||
return Jwts.parser()
|
||||
.verifyWith(getSigningKey())
|
||||
.build()
|
||||
.parseSignedClaims(token).getPayload();
|
||||
}
|
||||
|
||||
public String extractAccessJwtFromRequest(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
||||
return bearerToken.substring(7); // "Bearer " 제거
|
||||
}
|
||||
return bearerToken;
|
||||
}
|
||||
|
||||
public String extractRefreshJwtFromCookie(HttpServletRequest request) {
|
||||
if (request.getCookies() != null) {
|
||||
for (Cookie cookie : request.getCookies()) {
|
||||
if ("RefreshToken".equals(cookie.getName())) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
38
src/main/java/com/bio/bio_backend/global/utils/OidUtil.java
Normal file
38
src/main/java/com/bio/bio_backend/global/utils/OidUtil.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.bio.bio_backend.global.utils;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class OidUtil {
|
||||
private static final int MAX_SEQUENCE = 999;
|
||||
private static volatile Long lastTimestamp = null;
|
||||
private static AtomicInteger sequence = new AtomicInteger(0);
|
||||
private static final int SERVER_ID = resolveServerId();
|
||||
|
||||
public static synchronized long generateOid() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (lastTimestamp == null || now != lastTimestamp) {
|
||||
lastTimestamp = now;
|
||||
sequence.set(SERVER_ID);
|
||||
}
|
||||
|
||||
int index = sequence.getAndAdd(2);
|
||||
|
||||
if (index > MAX_SEQUENCE) {
|
||||
now += index / 1000;
|
||||
index = index % 1000;
|
||||
}
|
||||
|
||||
return now * 1000L + index;
|
||||
}
|
||||
|
||||
private static int resolveServerId() {
|
||||
try {
|
||||
// 서버 이중화
|
||||
// String ip = InetAddress.getLocalHost().getHostAddress();
|
||||
// if (ip.contains(".162")) return 1;
|
||||
// if (ip.contains(".163")) return 0;
|
||||
} catch (Exception ignored) {}
|
||||
return 1;
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package com.bio.bio_backend.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import com.bio.bio_backend.entity.Test;
|
||||
|
||||
public interface TestRepository extends JpaRepository<Test,Long>{
|
||||
|
||||
}
|
@@ -9,9 +9,9 @@ spring.devtools.restart.additional-paths=src/main/java
|
||||
|
||||
# 데이터베이스 연결 정보
|
||||
# URL 형식: jdbc:postgresql://[호스트명]:[포트번호]/[데이터베이스명]
|
||||
spring.datasource.url=jdbc:postgresql://stam.kr:15432/mms
|
||||
spring.datasource.username=mms_user
|
||||
spring.datasource.password=tam1201
|
||||
spring.datasource.url=jdbc:postgresql://stam.kr:15432/imas
|
||||
spring.datasource.username=imas_user
|
||||
spring.datasource.password=stam1201
|
||||
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
|
||||
# JPA/Hibernate 설정
|
||||
@@ -21,14 +21,36 @@ spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
# - update: 엔티티 변경 시 스키마 업데이트 (개발용)
|
||||
# - validate: 엔티티와 스키마 일치 여부만 검증 (운영용)
|
||||
# - none: 아무 작업도 하지 않음
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
|
||||
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=ddl/schema.sql
|
||||
spring.jpa.properties.hibernate.hbm2ddl.schema-generation.script.append=false
|
||||
|
||||
# SQL 쿼리를 콘솔에 표시
|
||||
spring.jpa.show-sql=true
|
||||
|
||||
# Hibernate가 SQL을 포맷하여 보여줌
|
||||
# Hibernate log
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.highlight_sql=true
|
||||
spring.jpa.properties.hibernate.use_sql_comments=false
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
logging.level.org.hibernate.orm.jdbc.bind=TRACE
|
||||
logging.level.org.springframework.data.jpa=DEBUG
|
||||
|
||||
# Open Session in View 설정 (권장: false)
|
||||
spring.jpa.open-in-view=false
|
||||
|
||||
# P6Spy
|
||||
decorator.datasource.p6spy.enable-logging=true
|
||||
decorator.datasource.p6spy.log-format=%(sqlSingleLine)
|
||||
|
||||
# CONSOLE
|
||||
spring.output.ansi.enabled=always
|
||||
|
||||
# HikariCP 연결 풀 크기 설정 (선택사항)
|
||||
# spring.datasource.hikari.maximum-pool-size=10
|
||||
|
||||
##JWT 설정
|
||||
## access : 30분 / refresh : 7일
|
||||
token.expiration_time_access=180000
|
||||
token.expiration_time_refresh=604800000
|
||||
token.secret_key= c3RhbV9qd3Rfc2VjcmV0X3Rva2Vuc3RhbV9qd3Rfc2VjcmV0X3Rva2Vu
|
||||
|
||||
|
Reference in New Issue
Block a user