-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from HongDam-org/feat/kakao-user
[FEAT] Kakao Login Init Setting
- Loading branch information
Showing
29 changed files
with
751 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
version: "3" | ||
|
||
services: | ||
db: | ||
image: mariadb:10 | ||
ports: | ||
- 3306:3306 | ||
env_file: .env | ||
environment: | ||
TZ: Asia/Seoul | ||
networks: | ||
- backend | ||
restart: always | ||
networks: | ||
backend: |
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
51 changes: 51 additions & 0 deletions
51
backend/src/main/java/com/twtw/backend/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,51 @@ | ||
package com.twtw.backend.config.security; | ||
|
||
import com.twtw.backend.config.security.jwt.JwtAccessDeniedHandler; | ||
import com.twtw.backend.config.security.jwt.JwtAuthenticationEntryPoint; | ||
import com.twtw.backend.config.security.jwt.JwtFilter; | ||
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.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.crypto.password.NoOpPasswordEncoder; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
public class SecurityConfig{ | ||
private final JwtFilter jwtFilter; | ||
private final JwtAccessDeniedHandler jwtAccessDeniedHandler; | ||
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; | ||
|
||
@Bean | ||
public SecurityFilterChain configure(HttpSecurity http) throws Exception{ | ||
return http.cors(cors -> cors.disable()).csrf(csrf -> csrf.disable()) | ||
.httpBasic(h -> h.disable()) | ||
.formLogin(f -> f.disable()) | ||
.authorizeHttpRequests( | ||
x->x.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html","auth/**") | ||
.permitAll() | ||
) | ||
.authorizeHttpRequests( | ||
x->x.requestMatchers("/test/**") | ||
.permitAll() | ||
.anyRequest() | ||
.authenticated() | ||
) | ||
.sessionManagement(x -> x.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | ||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) | ||
.exceptionHandling( | ||
x -> { | ||
x.authenticationEntryPoint(jwtAuthenticationEntryPoint); | ||
x.accessDeniedHandler(jwtAccessDeniedHandler); | ||
} | ||
).build(); | ||
} | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
backend/src/main/java/com/twtw/backend/config/security/jwt/JwtAccessDeniedHandler.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,18 @@ | ||
package com.twtw.backend.config.security.jwt; | ||
|
||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.security.access.AccessDeniedException; | ||
import org.springframework.security.web.access.AccessDeniedHandler; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
public class JwtAccessDeniedHandler implements AccessDeniedHandler { | ||
@Override | ||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { | ||
response.sendError(HttpServletResponse.SC_FORBIDDEN); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
backend/src/main/java/com/twtw/backend/config/security/jwt/JwtAuthenticationEntryPoint.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,19 @@ | ||
package com.twtw.backend.config.security.jwt; | ||
|
||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.AuthenticationEntryPoint; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
|
||
@Override | ||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
backend/src/main/java/com/twtw/backend/config/security/jwt/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,46 @@ | ||
package com.twtw.backend.config.security.jwt; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class JwtFilter extends OncePerRequestFilter { | ||
|
||
private final TokenProvider tokenProvider; | ||
private final String AUTHORIZATION_HEADER = "Authorization"; | ||
private final String BEARER_PREFIX = "Bearer "; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
String jwt = resolveToken(request); | ||
|
||
if(StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) | ||
{ | ||
Authentication authentication = tokenProvider.getAuthentication(jwt); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
filterChain.doFilter(request,response); | ||
} | ||
|
||
private String resolveToken(HttpServletRequest request) { | ||
String bearerToken = request.getHeader(AUTHORIZATION_HEADER); | ||
|
||
if(StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) | ||
{ | ||
return bearerToken.substring(7); | ||
} | ||
|
||
return null; | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
backend/src/main/java/com/twtw/backend/config/security/jwt/TokenProvider.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,120 @@ | ||
package com.twtw.backend.config.security.jwt; | ||
import com.twtw.backend.domain.member.dto.response.TokenDto; | ||
import com.twtw.backend.domain.member.entity.Member; | ||
import io.jsonwebtoken.*; | ||
import io.jsonwebtoken.io.Decoders; | ||
import io.jsonwebtoken.security.Keys; | ||
|
||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.beans.factory.annotation.Value; | ||
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.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Date; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Component | ||
public class TokenProvider implements InitializingBean { | ||
|
||
private Key key; | ||
private final String secretKey; | ||
private static final String AUTHORITIES_KEY = "auth"; | ||
private static final Long ACCESS_TOKEN_EXPIRE_LENGTH = 60L * 60 * 24 * 1000; // 1 Day | ||
private static final Long REFRESH_TOKEN_EXPIRE_LENGTH = 60L * 60 * 24 * 14 * 1000; // 14 Days | ||
|
||
public TokenProvider( | ||
@Value("${jwt.secret}") String secretKey | ||
){ | ||
this.secretKey = secretKey; | ||
} | ||
|
||
@Override | ||
public void afterPropertiesSet() throws Exception { | ||
byte[] keyBytes = Decoders.BASE64.decode(secretKey); | ||
this.key = Keys.hmacShaKeyFor(keyBytes); | ||
} | ||
|
||
|
||
public TokenDto createToken(Authentication authentication) { | ||
String authorities = authentication.getAuthorities().stream() | ||
.map(GrantedAuthority::getAuthority) | ||
.collect(Collectors.joining(",")); | ||
|
||
Long now = (new Date()).getTime(); | ||
Date validAccessDate = new Date(now + ACCESS_TOKEN_EXPIRE_LENGTH); | ||
Date validRefreshDate = new Date(now + REFRESH_TOKEN_EXPIRE_LENGTH); | ||
|
||
String accessToken = Jwts.builder() | ||
.setSubject(authentication.getName()) | ||
.claim(AUTHORITIES_KEY,authorities) | ||
.signWith(key, SignatureAlgorithm.HS512) | ||
.setExpiration(validAccessDate) | ||
.compact(); | ||
|
||
String refreshToken = Jwts.builder() | ||
.setExpiration(validRefreshDate) | ||
.signWith(key,SignatureAlgorithm.HS512) | ||
.compact(); | ||
|
||
return new TokenDto(accessToken,refreshToken); | ||
} | ||
|
||
public Authentication getAuthentication(String accessToken) { | ||
Claims claims = parseClaims(accessToken); | ||
|
||
if(claims.get(AUTHORITIES_KEY) == null) | ||
{ | ||
throw new RuntimeException("권한 정보가 없는 토큰입니다."); | ||
} | ||
|
||
Collection<GrantedAuthority> authorities = new ArrayList<>(); | ||
String role = claims.get(AUTHORITIES_KEY).toString(); | ||
|
||
if(role.equals("ROLE_ADMIN")) { | ||
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); | ||
} | ||
|
||
else if(role.equals("ROLE_USER")){ | ||
authorities.add(new SimpleGrantedAuthority("ROLE_USER")); | ||
} | ||
|
||
return new UsernamePasswordAuthenticationToken(claims.getSubject(),"",authorities); | ||
|
||
} | ||
|
||
public boolean validateToken(String token) { | ||
try{ | ||
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); | ||
return true; | ||
}catch (ExpiredJwtException | UnsupportedJwtException | IllegalStateException e) { | ||
return false; | ||
} | ||
} | ||
|
||
private Claims parseClaims(String accessToken) { | ||
try{ | ||
Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken).getBody(); | ||
return claims; | ||
}catch (ExpiredJwtException e) | ||
{ | ||
return e.getClaims(); | ||
} | ||
} | ||
|
||
public UsernamePasswordAuthenticationToken makeCredit(Member member) | ||
{ | ||
List<GrantedAuthority> role = new ArrayList<>(); | ||
role.add(new SimpleGrantedAuthority(member.getRole().toString())); | ||
UsernamePasswordAuthenticationToken credit = new UsernamePasswordAuthenticationToken(member.getId().toString(),"",role); | ||
|
||
return credit; | ||
} | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
backend/src/main/java/com/twtw/backend/domain/member/SwaggerConfiguration.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,31 @@ | ||
package com.twtw.backend.domain.member; | ||
|
||
import io.swagger.v3.oas.models.Components; | ||
import io.swagger.v3.oas.models.OpenAPI; | ||
import io.swagger.v3.oas.models.info.Info; | ||
import io.swagger.v3.oas.models.security.SecurityRequirement; | ||
import io.swagger.v3.oas.models.security.SecurityScheme; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import java.util.List; | ||
|
||
@Configuration | ||
public class SwaggerConfiguration { | ||
@Bean | ||
public OpenAPI getOpenAPI() { | ||
return new OpenAPI() | ||
.info( | ||
new Info().title("TWTW") | ||
.description("Hong Dam Jin") | ||
.version("v0.0.1") | ||
) | ||
.components( | ||
new Components().addSecuritySchemes( | ||
"bearerAuth", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") | ||
.in(SecurityScheme.In.HEADER).name("Authorization") | ||
) | ||
).security( | ||
List.of(new SecurityRequirement().addList("bearerAuth")) | ||
); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
backend/src/main/java/com/twtw/backend/domain/member/controller/AuthController.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,45 @@ | ||
package com.twtw.backend.domain.member.controller; | ||
|
||
import com.twtw.backend.domain.member.dto.request.MemberSaveRequest; | ||
import com.twtw.backend.domain.member.dto.response.TokenDto; | ||
import com.twtw.backend.domain.member.service.AuthService; | ||
import com.twtw.backend.domain.member.dto.request.OAuthRequest; | ||
import com.twtw.backend.domain.member.dto.request.TokenRequest; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequestMapping("/auth") | ||
public class AuthController { | ||
private final AuthService authService; | ||
|
||
public AuthController(AuthService authService) { | ||
this.authService = authService; | ||
} | ||
|
||
@PostMapping("/refresh") | ||
public ResponseEntity<TokenDto> authorize(@RequestBody TokenRequest tokenRequest) { | ||
return ResponseEntity.ok(authService.refreshToken(tokenRequest.getAccessToken(),tokenRequest.getRefreshToken())); | ||
} | ||
|
||
@PostMapping("/save") | ||
public ResponseEntity<TokenDto> saveMember(@RequestBody MemberSaveRequest memberSaveRequest) { | ||
TokenDto tokenDto = authService.saveMember(memberSaveRequest); | ||
|
||
return ResponseEntity.status(HttpStatus.OK).body(tokenDto); | ||
} | ||
|
||
@PostMapping("/login") | ||
public ResponseEntity<TokenDto> afterSocialLogin(@RequestBody OAuthRequest request){ | ||
TokenDto tokenDto = authService.getTokenByOAuth(request); | ||
|
||
if(tokenDto == null){ | ||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(tokenDto); | ||
} | ||
|
||
else{ | ||
return ResponseEntity.status(HttpStatus.OK).body(tokenDto); | ||
} | ||
} | ||
} |
Oops, something went wrong.