forked from kookmin-sw/cap-template
-
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 #287 from kookmin-sw/feature/284
Feat: Login & Join
- Loading branch information
Showing
17 changed files
with
421 additions
and
170 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
13 changes: 13 additions & 0 deletions
13
server/src/main/java/com/capstone/server/config/BCryptConfig.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,13 @@ | ||
package com.capstone.server.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
|
||
@Configuration | ||
public class BCryptConfig { | ||
@Bean | ||
public BCryptPasswordEncoder passwordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
server/src/main/java/com/capstone/server/config/JwtTokenFilter.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,73 @@ | ||
package com.capstone.server.config; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
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 com.capstone.server.model.UserEntity; | ||
import com.capstone.server.service.JwtTokenService; | ||
import com.capstone.server.service.UserService; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
// OncePerRequestFilter : 매번 들어갈 때 마다 체크 해주는 필터 | ||
@RequiredArgsConstructor | ||
public class JwtTokenFilter extends OncePerRequestFilter { | ||
|
||
private final JwtTokenService jwtTokenService; | ||
private final UserService userService; | ||
private final String secretKey; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); | ||
|
||
// Header의 Authorization 값이 비어있으면 => Jwt Token을 전송하지 않음 => 로그인 하지 않음 | ||
if(authorizationHeader == null) { | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
// Header의 Authorization 값이 'Bearer '로 시작하지 않으면 => 잘못된 토큰 | ||
if(!authorizationHeader.startsWith("Bearer ")) { | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
// 전송받은 값에서 'Bearer ' 뒷부분(Jwt Token) 추출 | ||
String token = authorizationHeader.split(" ")[1]; | ||
|
||
// 전송받은 Jwt Token이 만료되었으면 => 다음 필터 진행(인증 X) | ||
if (jwtTokenService.isExpired(token, secretKey)) { | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
// Jwt Token에서 loginId 추출 | ||
String loginId = jwtTokenService.getLoginId(token, secretKey); | ||
|
||
// 추출한 loginId로 User 찾아오기 | ||
UserEntity loginUser = userService.getLoginUserByLoginId(loginId); | ||
|
||
// loginUser 정보로 UsernamePasswordAuthenticationToken 발급 | ||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( | ||
loginUser.getLoginId(), null, List.of(new SimpleGrantedAuthority(loginUser.getRole().name()))); | ||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||
|
||
// 권한 부여 | ||
SecurityContextHolder.getContext().setAuthentication(authenticationToken); | ||
filterChain.doFilter(request, response); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
server/src/main/java/com/capstone/server/config/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.capstone.server.config; | ||
|
||
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.annotation.web.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.config.http.SessionCreationPolicy; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
import com.capstone.server.model.enums.UserRole; | ||
import com.capstone.server.service.JwtTokenService; | ||
import com.capstone.server.service.UserService; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@RequiredArgsConstructor | ||
public class SecurityConfig { | ||
private final JwtTokenService jwtTokenService; | ||
private final UserService userService; | ||
|
||
@Value("${jwt.secretKey}") | ||
private String secretKey; | ||
|
||
@Bean | ||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { | ||
return httpSecurity | ||
.httpBasic(http -> http.disable()) | ||
.csrf(csrf -> csrf.disable()) | ||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | ||
.addFilterBefore(new JwtTokenFilter(jwtTokenService, userService, secretKey), UsernamePasswordAuthenticationFilter.class) | ||
.authorizeHttpRequests(auth -> auth | ||
.requestMatchers("/api/guardian/**").permitAll() | ||
.requestMatchers(HttpMethod.GET, "/api/missing-people").permitAll() | ||
.requestMatchers("/api/user/info/**").authenticated() | ||
.requestMatchers("/api/user/**").permitAll() | ||
.anyRequest().hasAuthority(UserRole.ADMIN.name()) | ||
) | ||
.build(); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
server/src/main/java/com/capstone/server/controller/JwtLoginApiController.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,67 @@ | ||
package com.capstone.server.controller; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.capstone.server.dto.login.JoinRequestDto; | ||
import com.capstone.server.dto.login.LoginRequestDto; | ||
import com.capstone.server.dto.login.LoginResponseDto; | ||
import com.capstone.server.model.UserEntity; | ||
import com.capstone.server.response.SuccessResponse; | ||
import com.capstone.server.service.JwtTokenService; | ||
import com.capstone.server.service.UserService; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/user") | ||
public class JwtLoginApiController { | ||
@Value("${jwt.secretKey}") | ||
private String secretKey; | ||
@Value("${jwt.expireTime}") | ||
private long expireTime; | ||
|
||
@Autowired | ||
private UserService userService; | ||
@Autowired | ||
private JwtTokenService jwtTokenService; | ||
|
||
@PostMapping("/join") | ||
public ResponseEntity<?> join(@RequestBody JoinRequestDto joinRequestDto) { | ||
|
||
// loginId 중복 체크 | ||
userService.checkLoginIdDuplicate(joinRequestDto.getLoginId()); | ||
|
||
// 회원가입 | ||
userService.join(joinRequestDto); | ||
return ResponseEntity.ok().body(new SuccessResponse("Join Success")); | ||
} | ||
|
||
@PostMapping("/login") | ||
public ResponseEntity<?> login(@RequestBody LoginRequestDto loginRequestDto) { | ||
// 로그인 | ||
UserEntity user = userService.login(loginRequestDto); | ||
|
||
// Jwt Token 발급 | ||
String jwtToken = jwtTokenService.createToken(user.getLoginId(), secretKey, expireTime); | ||
|
||
LoginResponseDto loginResponseDto = new LoginResponseDto(user, jwtToken); | ||
return ResponseEntity.ok().body(new SuccessResponse(loginResponseDto)); | ||
} | ||
|
||
@GetMapping("/info") | ||
public ResponseEntity<?> userInfo(Authentication auth) { | ||
UserEntity loginUser = userService.getLoginUserByLoginId(auth.getName()); | ||
|
||
return ResponseEntity.ok().body(new SuccessResponse(String.format("loginId : %s, role : %s", | ||
loginUser.getLoginId(), loginUser.getRole().name()))); | ||
} | ||
} |
61 changes: 0 additions & 61 deletions
61
server/src/main/java/com/capstone/server/controller/UserApiController.java
This file was deleted.
Oops, something went wrong.
41 changes: 0 additions & 41 deletions
41
server/src/main/java/com/capstone/server/dto/UserCreateRequestDto.java
This file was deleted.
Oops, something went wrong.
17 changes: 0 additions & 17 deletions
17
server/src/main/java/com/capstone/server/dto/UserUpdateRequestDto.java
This file was deleted.
Oops, something went wrong.
28 changes: 28 additions & 0 deletions
28
server/src/main/java/com/capstone/server/dto/login/JoinRequestDto.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,28 @@ | ||
package com.capstone.server.dto.login; | ||
|
||
import com.capstone.server.model.UserEntity; | ||
import com.capstone.server.model.enums.UserRole; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
public class JoinRequestDto { | ||
@NotBlank(message = "아이디가 비었습니다.") | ||
private String loginId; | ||
|
||
@NotBlank(message = "비밀번호가 비었습니다.") | ||
private String password; | ||
|
||
public UserEntity toEntity(String encodedPassword) { | ||
return UserEntity.builder() | ||
.loginId(this.loginId) | ||
.password(encodedPassword) | ||
.role(UserRole.USER) | ||
.build(); | ||
} | ||
} |
Oops, something went wrong.