Skip to content

Commit

Permalink
Merge pull request #13 from Team-INSERT/Feat/Security
Browse files Browse the repository at this point in the history
Feat/security
  • Loading branch information
jacobhboy authored Aug 28, 2023
2 parents 9df2f6c + ebafc6e commit 0bb2be5
Show file tree
Hide file tree
Showing 46 changed files with 1,229 additions and 35 deletions.
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ configurations {

repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}

dependencies {
Expand All @@ -28,7 +29,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.hibernate.validator:hibernate-validator:8.0.1.Final'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'com.github.leehj050211:bsm-oauth-java:1.0.3'

testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
Expand All @@ -38,8 +41,11 @@ dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'

compileOnly 'org.projectlombok:lombok'
compileOnly 'io.jsonwebtoken:jjwt-api:0.11.5'

runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'

annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/insert/ogbsm/OgBsmApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EnableJpaAuditing
@ConfigurationPropertiesScan
@EnableJpaRepositories
@SpringBootApplication
public class OgBsmApplication {

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/insert/ogbsm/domain/auth/AuthId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.insert.ogbsm.domain.auth;

import lombok.*;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;
import org.springframework.data.redis.core.index.Indexed;

import javax.persistence.Id;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
@RedisHash
public class AuthId {
@Id
String id;

@Indexed
String authId;

@TimeToLive
private long ttl;
}
34 changes: 34 additions & 0 deletions src/main/java/com/insert/ogbsm/domain/auth/RefreshToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.insert.ogbsm.domain.auth;

import lombok.*;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;
import org.springframework.data.redis.core.index.Indexed;

import javax.persistence.Id;
import java.time.ZonedDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
@RedisHash
public class RefreshToken {
@Id
private String id;
@Indexed
private String refreshToken;

private String role;

@TimeToLive
private long ttl;

private ZonedDateTime expiredAt;

public RefreshToken update(final String refreshToken, final long ttl) {
this.refreshToken = refreshToken;
this.ttl = ttl;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.insert.ogbsm.domain.auth.exception;

import com.insert.ogbsm.domain.user.exception.UserNotFoundException;
import com.insert.ogbsm.global.error.exception.BsmException;
import com.insert.ogbsm.global.error.exception.ErrorCode;

public class InvalidClientException extends BsmException {
public static final UserNotFoundException EXCEPTION = new UserNotFoundException(ErrorCode.BSM_AUTH_INVALID_CLIENT);

public InvalidClientException(ErrorCode errorCode) {
super(errorCode);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/insert/ogbsm/domain/auth/repo/AuthIdRepo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.insert.ogbsm.domain.auth.repo;

import com.insert.ogbsm.domain.auth.AuthId;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface AuthIdRepo extends CrudRepository<AuthId, String> {
Optional<AuthId> findByAuthId(String authId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.insert.ogbsm.domain.auth.repo;

import com.insert.ogbsm.domain.auth.RefreshToken;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface RefreshTokenRepo extends CrudRepository<RefreshToken, String> {
Optional<RefreshToken> findById(String authId);
Optional<RefreshToken> findByRefreshToken(String refreshToken);
}
61 changes: 38 additions & 23 deletions src/main/java/com/insert/ogbsm/domain/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@

import com.insert.ogbsm.domain.user.authority.Authority;
import com.insert.ogbsm.domain.user.role.Role;
import jakarta.persistence.*;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import leehj050211.bsmOauth.dto.resource.BsmStudent;
import leehj050211.bsmOauth.dto.resource.BsmTeacher;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;


@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {

Expand All @@ -20,42 +31,46 @@ public class User {
@Column(unique = true, nullable = false)
private String nickname;

@Column(unique = true,nullable = false)
@Column(unique = true, nullable = false)
private String email;

@Column()
private String name;

@Column()
private String profile_image;

@Enumerated(EnumType.STRING)
private Authority authority;

@Enumerated(EnumType.STRING)
private Role role;

@Min(2021)
private Long enroll;

@Column()
@Min(1)
@Max(3)
private Long grade;
private Short grade;

@Column()
@Min(1)
@Max(4)
private Long class_number;
private Short class_number;

@Column()
@Min(1)
@Max(16)
private Long student_number;

@Column()
private String profile_image;

@Enumerated(EnumType.STRING)
@Column()
private Authority authority;

@Enumerated(EnumType.STRING)
@Column()
private Role role;


private Short student_number;

public void setTeacherValue(BsmTeacher teacher) {
this.name = teacher.getName();
this.role = Role.TEACHER;
}

public void setStudentValue(BsmStudent student) {
this.name = student.getName();
this.role = Role.STUDENT;
this.enroll = student.getEnrolledAt().longValue();
this.grade = student.getGrade().shortValue();
this.class_number = student.getClassNo().shortValue();
this.student_number = student.getStudentNo().shortValue();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.insert.ogbsm.domain.user.exception;

import com.insert.ogbsm.global.error.exception.BsmException;
import com.insert.ogbsm.global.error.exception.ErrorCode;

public class UserNotFoundException extends BsmException {

public static final UserNotFoundException EXCEPTION = new UserNotFoundException(ErrorCode.USER_NOT_FOUND);

public UserNotFoundException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.insert.ogbsm.domain.user.exception;

import com.insert.ogbsm.global.error.exception.BsmException;
import com.insert.ogbsm.global.error.exception.ErrorCode;

public class UserNotLoginException extends BsmException {

public static final UserNotFoundException EXCEPTION = new UserNotFoundException(ErrorCode.USER_NOT_LOGIN);

public UserNotLoginException(ErrorCode errorCode) {
super(errorCode);
}
}
6 changes: 4 additions & 2 deletions src/main/java/com/insert/ogbsm/domain/user/repo/UserRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.insert.ogbsm.domain.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

public interface UserRepo extends JpaRepository<User, Long> {

import java.util.Optional;

public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findByEmail(String id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.insert.ogbsm.global.error;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.insert.ogbsm.global.error.exception.ErrorCode;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import java.io.IOException;

@RequiredArgsConstructor
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

private final ObjectMapper objectMapper;

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
ErrorCode errorCode = ErrorCode.FORBIDDEN;
String errorResponseJson = objectMapper.writeValueAsString(
new ErrorResponse(errorCode.getStatus(), errorCode.getCode(), errorCode.getMessage()));

response.setStatus(errorCode.getStatus());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(errorResponseJson);
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/insert/ogbsm/global/error/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.insert.ogbsm.global.error;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ErrorResponse {
private int status;
private String code;
private String message;

public String toString() {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/insert/ogbsm/global/error/ExceptionFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.insert.ogbsm.global.error;

import com.insert.ogbsm.global.error.exception.BsmException;
import com.insert.ogbsm.global.error.exception.ErrorCode;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

public class ExceptionFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException {
try {
filterChain.doFilter(request, response);
} catch (BsmException e) {
writeErrorCode(response, e.getErrorCode());
} catch (ExpiredJwtException e) {
writeErrorCode(response, ErrorCode.EXPIRED_JWT);
} catch (JwtException e) {
writeErrorCode(response, ErrorCode.INVALID_TOKEN);
} catch (Exception e) {
e.printStackTrace();
writeErrorCode(response, ErrorCode.INTERNAL_SERVER_ERROR);
}
}

private void writeErrorCode(HttpServletResponse response, ErrorCode errorCode) throws IOException {
ErrorResponse errorResponse = new ErrorResponse(
errorCode.getStatus(), errorCode.getCode(), errorCode.getMessage()
);

response.setStatus(errorResponse.getStatus());
response.setCharacterEncoding("UTF-8");
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(errorResponse.toString());
}
}
Loading

0 comments on commit 0bb2be5

Please sign in to comment.