-
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.
✨ Security 의존성 추가, securityConfig, jwtFilter, jwtProvider 생성
- Loading branch information
Showing
4 changed files
with
185 additions
and
0 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
48 changes: 48 additions & 0 deletions
48
src/main/java/com/dnd/dndtravel/auth/config/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,48 @@ | ||
package com.dnd.dndtravel.auth.config; | ||
|
||
import io.jsonwebtoken.io.IOException; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.ServletRequest; | ||
import jakarta.servlet.ServletResponse; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.filter.GenericFilterBean; | ||
|
||
@RequiredArgsConstructor | ||
public class JwtFilter extends GenericFilterBean { | ||
|
||
public static final String ACCESS_HEADER= "Authorization"; | ||
private final JwtProvider jwtProvider; | ||
|
||
@Override | ||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException, java.io.IOException { | ||
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; | ||
String token = resolveToken(httpServletRequest); | ||
String requestURI = httpServletRequest.getRequestURI(); | ||
|
||
if (StringUtils.hasText(token) && jwtProvider.validateToken(token)) { | ||
Authentication authentication = jwtProvider.getAuthentication(token); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
else { | ||
System.out.println("유효한 jwt 토큰이 없습니다. uri: " + requestURI); | ||
} | ||
|
||
filterChain.doFilter(servletRequest, servletResponse); | ||
} | ||
|
||
// Request Header 토큰 정보 추출 | ||
private String resolveToken(HttpServletRequest request) { | ||
String bearerToken = request.getHeader(ACCESS_HEADER); | ||
|
||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { | ||
return bearerToken.substring(7); | ||
} | ||
|
||
return null; | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
src/main/java/com/dnd/dndtravel/auth/config/JwtProvider.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,101 @@ | ||
package com.dnd.dndtravel.auth.config; | ||
|
||
import io.jsonwebtoken.*; | ||
import io.jsonwebtoken.io.Decoders; | ||
import io.jsonwebtoken.security.Keys; | ||
import io.jsonwebtoken.security.SecurityException; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.security.Key; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Date; | ||
import java.util.stream.Collectors; | ||
|
||
@Component | ||
public class JwtProvider implements InitializingBean { | ||
|
||
private static final String AUTHORITIES_KEY = "memberId"; | ||
private final long tokenValidityInMilliseconds; | ||
private final String secretKey; | ||
private Key key; | ||
|
||
public JwtProvider( | ||
@Value("${JWT_SECRET_KEY}") String secretKey, | ||
@Value("86400") long tokenValidityInSeconds) { | ||
this.secretKey = secretKey; | ||
this.tokenValidityInMilliseconds = tokenValidityInSeconds * 1000; | ||
} | ||
|
||
// secretKey 값을 Base64 Decode 해서 key 변수에 할당 | ||
@Override | ||
public void afterPropertiesSet() { | ||
byte[] keyBytes = Decoders.BASE64.decode(secretKey); | ||
this.key = Keys.hmacShaKeyFor(keyBytes); | ||
} | ||
|
||
// JWT Access 토큰 생성 | ||
public String createToken(Authentication authentication) { | ||
Long memberId = Long.parseLong(authentication.getName()); | ||
long now = (new Date()).getTime(); | ||
Date validity = new Date(now + this.tokenValidityInMilliseconds); //1일 | ||
|
||
return Jwts.builder() | ||
.setSubject(String.valueOf(memberId)) | ||
.claim(AUTHORITIES_KEY, memberId) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.setExpiration(validity) | ||
.compact(); | ||
} | ||
|
||
// Refresh 토큰 생성 | ||
public String createRefreshToken(Long memberId) { | ||
long now = (new Date()).getTime(); | ||
Date validity = new Date(now + this.tokenValidityInMilliseconds * 14); // 14일 | ||
|
||
return Jwts.builder() | ||
.setSubject(String.valueOf(memberId)) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.setExpiration(validity) | ||
.compact(); | ||
} | ||
|
||
// authentication 객체 생성 | ||
public Authentication getAuthentication(String token) { | ||
Claims claims = Jwts.parser() | ||
.setSigningKey(key) | ||
.build() | ||
.parseClaimsJws(token) | ||
.getBody(); | ||
Collection<? extends GrantedAuthority> authorities = | ||
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) | ||
.map(SimpleGrantedAuthority::new) | ||
.collect(Collectors.toList()); | ||
|
||
return new UsernamePasswordAuthenticationToken(claims.get(AUTHORITIES_KEY), token, authorities); | ||
} | ||
|
||
// Token 유효성 검증 | ||
public boolean validateToken(String token) { | ||
try { | ||
Jwts.parser().setSigningKey(key).build().parseClaimsJws(token); | ||
return true; | ||
} catch (SecurityException | MalformedJwtException e) { | ||
System.out.println("잘못된 JWT Signature"); | ||
} catch (ExpiredJwtException e) { | ||
System.out.println("만료된 JWT 토큰"); | ||
} catch (UnsupportedJwtException e) { | ||
System.out.println("지원 되지 않는 JWT 토큰"); | ||
} catch (IllegalArgumentException e) { | ||
System.out.println("잘못된 JWT 토큰"); | ||
} | ||
|
||
return false; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/main/java/com/dnd/dndtravel/auth/config/JwtSecurityConfig.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,35 @@ | ||
package com.dnd.dndtravel.auth.config; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
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 JwtSecurityConfig { | ||
|
||
private final JwtProvider jwtProvider; | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
http | ||
.csrf() | ||
.disable() | ||
.sessionManagement() | ||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
.and() | ||
.authorizeHttpRequests() | ||
.requestMatchers("/login/**").permitAll() | ||
.anyRequest().authenticated() | ||
.and() | ||
.addFilterBefore(new JwtFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class); | ||
|
||
return http.build(); | ||
} | ||
} |