-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Feat: WebSecurity 설정 및 Jwt 토큰 생성 기능 구현 (#31)
- Loading branch information
Showing
3 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
src/main/java/com/diareat/diareat/auth/component/JwtAuthFilter.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,36 @@ | ||
package com.diareat.diareat.auth.component; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.web.filter.GenericFilterBean; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.ServletRequest; | ||
import javax.servlet.ServletResponse; | ||
import javax.servlet.http.HttpServletRequest; | ||
import java.io.IOException; | ||
|
||
@RequiredArgsConstructor | ||
public class JwtAuthFilter extends GenericFilterBean { | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
// 헤더에서 토큰 받아오기 | ||
String token = jwtTokenProvider.resolveToken((HttpServletRequest) request); | ||
|
||
// 토큰이 유효하다면 | ||
if (token != null && jwtTokenProvider.validateToken(token)) { | ||
// 토큰으로부터 유저 정보를 받아 | ||
Authentication authentication = jwtTokenProvider.getAuthentication(token); | ||
// SecurityContext 에 객체 저장 | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
|
||
// 다음 Filter 실행 | ||
chain.doFilter(request, response); | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
src/main/java/com/diareat/diareat/auth/component/JwtTokenProvider.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,72 @@ | ||
package com.diareat.diareat.auth.component; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jws; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.SignatureAlgorithm; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.core.userdetails.UserDetailsService; | ||
import org.springframework.stereotype.Component; | ||
|
||
import javax.annotation.PostConstruct; | ||
import javax.servlet.http.HttpServletRequest; | ||
import java.util.Base64; | ||
import java.util.Date; | ||
|
||
@RequiredArgsConstructor | ||
@Component | ||
public class JwtTokenProvider { | ||
|
||
@Value("${jwt.secret}") | ||
private String secretKey; | ||
|
||
private final UserDetailsService userDetailsService; | ||
|
||
// 객체 초기화, secretKey를 Base64로 인코딩 | ||
@PostConstruct | ||
protected void init() { | ||
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); | ||
} | ||
|
||
// 토큰 생성 | ||
public String createToken(String userPk) { | ||
Claims claims = Jwts.claims().setSubject(userPk); // JWT payload 에 저장되는 정보단위 | ||
Date now = new Date(); | ||
return Jwts.builder() | ||
.setClaims(claims) // 정보 저장 | ||
.setIssuedAt(now) // 토큰 발행 시간 정보 | ||
.setExpiration(new Date(now.getTime() + (30 * 60 * 1000L))) // 토큰 유효시각 설정 (30분) | ||
.signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘과, secret 값 | ||
.compact(); | ||
} | ||
|
||
// 인증 정보 조회 | ||
public Authentication getAuthentication(String token) { | ||
UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUserPk(token)); | ||
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); | ||
} | ||
|
||
// 토큰에서 회원 정보 추출 | ||
public String getUserPk(String token) { | ||
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); | ||
} | ||
|
||
// 토큰 유효성, 만료일자 확인 | ||
public boolean validateToken(String jwtToken) { | ||
try { | ||
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); | ||
return !claims.getBody().getExpiration().before(new Date()); | ||
} catch (Exception e) { | ||
return false; | ||
} | ||
} | ||
|
||
// Request의 Header에서 token 값 가져오기 | ||
public String resolveToken(HttpServletRequest request) { | ||
return request.getHeader("X-AUTH-TOKEN"); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/diareat/diareat/config/WebSecurityConfig.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,36 @@ | ||
package com.diareat.diareat.config; | ||
|
||
import com.diareat.diareat.auth.component.JwtAuthFilter; | ||
import com.diareat.diareat.auth.component.JwtTokenProvider; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Bean; | ||
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; | ||
|
||
@RequiredArgsConstructor | ||
@EnableWebSecurity | ||
public class WebSecurityConfig { | ||
|
||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
http | ||
.csrf().disable() | ||
//세션 사용 안함 | ||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
.and() | ||
//URL 관리 | ||
.authorizeRequests() | ||
.antMatchers("/api/auth/**").permitAll() // 이 API 는 누구나 접근 가능 | ||
.anyRequest().authenticated() | ||
.and() | ||
// JwtAuthenticationFilter를 먼저 적용 | ||
.addFilterBefore(new JwtAuthFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); | ||
|
||
return http.build(); | ||
} | ||
} |