-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[FEAT]#13 JWT access-token, 스프링 시큐리티 적용 로그인 기능 구현
- Loading branch information
Showing
12 changed files
with
274 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/main/java/com/example/rcp1/domain/user/domain/repository/UserRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,14 @@ | ||
package com.example.rcp1.domain.user.domain.repository; | ||
|
||
import com.example.rcp1.domain.user.domain.User; | ||
import com.example.rcp1.domain.user.dto.SignInReq; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
|
||
import java.util.Optional; | ||
|
||
public interface UserRepository extends JpaRepository<User, Long> { | ||
|
||
|
||
Optional<User> findByEmail(String email); | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/example/rcp1/domain/user/dto/SignInReq.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.example.rcp1.domain.user.dto; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.Data; | ||
|
||
@Data | ||
public class SignInReq { | ||
@NotBlank | ||
private String email; | ||
|
||
@NotBlank | ||
private String password; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/com/example/rcp1/global/CustomAuthenticationException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.example.rcp1.global; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
public class CustomAuthenticationException extends RuntimeException { | ||
public CustomAuthenticationException(String message) { | ||
super(message); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
src/main/java/com/example/rcp1/global/config/security/JwtFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.example.rcp1.global.config.security; | ||
|
||
import com.example.rcp1.domain.user.application.UserService; | ||
import com.example.rcp1.global.config.security.util.JwtUtil; | ||
import jakarta.servlet.Filter; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class JwtFilter extends OncePerRequestFilter { | ||
|
||
|
||
private final UserService userService; | ||
@Value("${SECRET_KEY}") | ||
private final String secretKey; | ||
|
||
// 필터 관문 | ||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
|
||
final String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); | ||
log.info("authorization : {}", authorization); | ||
|
||
// 토큰 안보내면 블락 | ||
if (authorization == null || !authorization.startsWith("Bearer ")) { | ||
// log.error("authentication을 잘못 보냈습니다."); | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
// 토큰 꺼내기 | ||
String token = authorization.split(" ")[1]; | ||
|
||
// 토큰 만료 여부 확인 | ||
if (JwtUtil.isExpired(token, secretKey)) { | ||
log.error("토큰이 만료되었습니다."); | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
// UserName Token에서 꺼내기 | ||
String email = JwtUtil.getUserEmail(token, secretKey); | ||
log.info("email:{}", email); | ||
|
||
// 권한 부여 | ||
UsernamePasswordAuthenticationToken authenticationToken = | ||
new UsernamePasswordAuthenticationToken(email, null, List.of(new SimpleGrantedAuthority("USER"))); | ||
|
||
// Detail | ||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||
SecurityContextHolder.getContext().setAuthentication(authenticationToken); | ||
filterChain.doFilter(request, response); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/com/example/rcp1/global/config/security/SecurityConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.example.rcp1.global.config.security; | ||
|
||
import com.example.rcp1.domain.user.application.UserService; | ||
import com.example.rcp1.domain.user.domain.repository.UserRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.http.SessionCreationPolicy; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
public class SecurityConfig { | ||
|
||
private final UserService userService; | ||
|
||
@Value("${SECRET_KEY}") | ||
private String secretKey; | ||
|
||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
return http | ||
.httpBasic().disable() | ||
.csrf().disable() | ||
.cors().and() | ||
.authorizeHttpRequests() | ||
.requestMatchers("/user/signUp", "/user/signIn").permitAll() | ||
.requestMatchers(HttpMethod.POST, "/user/**").authenticated() | ||
.and() | ||
.sessionManagement() | ||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
.and() | ||
.addFilterBefore(new JwtFilter(userService, secretKey), UsernamePasswordAuthenticationFilter.class) | ||
.build(); | ||
} | ||
|
||
|
||
|
||
} |
32 changes: 32 additions & 0 deletions
32
src/main/java/com/example/rcp1/global/config/security/util/JwtUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.example.rcp1.global.config.security.util; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.SignatureAlgorithm; | ||
|
||
import java.util.Date; | ||
|
||
public class JwtUtil { | ||
|
||
public static String getUserEmail(String token, String secretkey) { | ||
return Jwts.parser().setSigningKey(secretkey).parseClaimsJws(token) | ||
.getBody().get("email", String.class); | ||
} | ||
|
||
public static boolean isExpired(String token, String secretkey) { | ||
System.out.println("token = " + token); | ||
return Jwts.parser().setSigningKey(secretkey).parseClaimsJws(token).getBody().getExpiration().before(new Date()); | ||
} | ||
|
||
public static String createJwt(String email, String secretKey, Long expiredMs) { | ||
Claims claims = Jwts.claims(); | ||
claims.put("email", email); | ||
|
||
return Jwts.builder() | ||
.setClaims(claims) | ||
.setIssuedAt(new Date(System.currentTimeMillis())) | ||
.setExpiration(new Date(System.currentTimeMillis() + expiredMs)) | ||
.signWith(SignatureAlgorithm.HS256, secretKey) | ||
.compact(); | ||
} | ||
} |