Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : CutomUserDetails 추가 #21

Merged
merged 1 commit into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions src/main/java/com/zonebug/debugging/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.zonebug.debugging.config;


import com.zonebug.debugging.config.jwt.JwtAccessDeniedHandler;
import com.zonebug.debugging.config.jwt.JwtAuthenticationEntryPoint;
import com.zonebug.debugging.config.jwt.JwtSecurityConfig;
import com.zonebug.debugging.config.jwt.TokenProvider;
import com.zonebug.debugging.security.jwt.JwtAccessDeniedHandler;
import com.zonebug.debugging.security.jwt.JwtAuthenticationEntryPoint;
import com.zonebug.debugging.security.jwt.JwtSecurityConfig;
import com.zonebug.debugging.security.jwt.TokenProvider;
import com.zonebug.debugging.security.user.CustomUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand All @@ -21,15 +22,18 @@ public class WebSecurityConfig {
private final TokenProvider tokenProvider;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final CustomUserDetailsService customUserDetailsService;

public WebSecurityConfig(
TokenProvider tokenProvider,
JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint,
JwtAccessDeniedHandler jwtAccessDeniedHandler
JwtAccessDeniedHandler jwtAccessDeniedHandler,
CustomUserDetailsService customUserDetailsService
) {
this.tokenProvider = tokenProvider;
this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
this.customUserDetailsService = customUserDetailsService;
}

@Bean
Expand Down Expand Up @@ -58,13 +62,18 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.and()
.authorizeHttpRequests((req) ->
req
.requestMatchers("/user/authenticate", "/user/signup").permitAll()
.requestMatchers("/user/authenticate", "/user/signup", "/user/signin").permitAll()
.requestMatchers("/oauth", "/oauth/kakao", "/oauth/callback/kakao", "/oauth/naver/**").permitAll()
.requestMatchers("/source/url").permitAll()
.anyRequest().authenticated()
)
.userDetailsService(customUserDetailsService)



.apply(new JwtSecurityConfig(tokenProvider));


return http.build();
}

Expand Down
50 changes: 0 additions & 50 deletions src/main/java/com/zonebug/debugging/controller/AuthController.java

This file was deleted.

58 changes: 53 additions & 5 deletions src/main/java/com/zonebug/debugging/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,75 @@
package com.zonebug.debugging.controller;

import com.zonebug.debugging.config.jwt.JwtFilter;
import com.zonebug.debugging.domain.user.User;
import com.zonebug.debugging.dto.LoginDto;
import com.zonebug.debugging.dto.TokenDto;
import com.zonebug.debugging.dto.UserDto;
import com.zonebug.debugging.security.jwt.JwtFilter;
import com.zonebug.debugging.security.jwt.TokenProvider;
import com.zonebug.debugging.security.user.CustomUserDetails;
import com.zonebug.debugging.service.UserService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {

private final UserService userService;
private final TokenProvider tokenProvider;
private final AuthenticationManagerBuilder authenticationManagerBuilder;


public UserController(UserService userService) {
this.userService = userService;
@GetMapping("")
public ResponseEntity<User> userOk(@AuthenticationPrincipal CustomUserDetails principalDetails) {
return ResponseEntity.ok(principalDetails.getUser());
}


@PostMapping("/signup")
public ResponseEntity<User> signup(@Valid @RequestBody UserDto userDto) {
return ResponseEntity.ok(userService.signup(userDto));
public ResponseEntity<User> signUp(@Valid @RequestBody UserDto userDto) {
return ResponseEntity.ok(userService.signUp(userDto));
}

@PostMapping("/signin")
public ResponseEntity<TokenDto> signIn(@Valid @RequestBody LoginDto loginDto) {
return ResponseEntity.ok(userService.signIn(loginDto));
}

@PostMapping("/authenticate")
public ResponseEntity<TokenDto> authorize(@Valid @RequestBody LoginDto loginDto) {

UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword());

Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
String accessToken = tokenProvider.createAccessToken(authentication);
String refreshToken = tokenProvider.createRefreshToken(authentication);

return new ResponseEntity(new TokenDto(accessToken, refreshToken), HttpStatus.OK);
}

@GetMapping("/info")
public ResponseEntity<Optional<User>> info() {
return ResponseEntity.ok(userService.getCurrentUser());
}

// Authentication 회원 정보
@GetMapping("/info2")
public ResponseEntity<User> user(@AuthenticationPrincipal CustomUserDetails principalDetails) {
User user = principalDetails.getUser();

return ResponseEntity.ok(principalDetails.getUser());
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/zonebug/debugging/dto/TokenDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@NoArgsConstructor
public class TokenDto {

private String token;
private String accessToken;
private String refreshToken;

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zonebug.debugging.config.jwt;
package com.zonebug.debugging.security.jwt;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zonebug.debugging.config.jwt;
package com.zonebug.debugging.security.jwt;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zonebug.debugging.config.jwt;
package com.zonebug.debugging.security.jwt;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zonebug.debugging.config.jwt;
package com.zonebug.debugging.security.jwt;

import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.zonebug.debugging.config.jwt;
package com.zonebug.debugging.security.jwt;

import com.zonebug.debugging.security.user.CustomUserDetails;
import com.zonebug.debugging.security.user.CustomUserDetailsService;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
Expand All @@ -24,6 +26,7 @@
public class TokenProvider implements InitializingBean {

private final Logger logger = LoggerFactory.getLogger(TokenProvider.class);
private final CustomUserDetailsService customUserDetailsService;

private static final String AUTHORITIES_KEY = "auth";
private final String secret;
Expand All @@ -32,9 +35,10 @@ public class TokenProvider implements InitializingBean {
private Key key;

public TokenProvider(
@Value("${jwt.secret}") String secret,
CustomUserDetailsService customUserDetailsService, @Value("${jwt.secret}") String secret,
@Value("${jwt.accesstoken-validity-in-seconds}") long accessTokenValidityInMilliseconds,
@Value("${jwt.refreshtoken-validity-in-seconds}") long refreshTokenValidityInMilliseconds) {
this.customUserDetailsService = customUserDetailsService;
this.secret = secret;
this.accessTokenValidityInMilliseconds = accessTokenValidityInMilliseconds * 1000;
this.refreshTokenValidityInMilliseconds = refreshTokenValidityInMilliseconds;
Expand Down Expand Up @@ -92,18 +96,23 @@ public Authentication getAuthentication(String token) {
.build()
.parseClaimsJws(token)
.getBody();

Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());

User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);

CustomUserDetails customUserDetails = (CustomUserDetails) customUserDetailsService.loadUserByUsername(principal.getUsername());
return new UsernamePasswordAuthenticationToken(customUserDetails, token, authorities);
}


public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
logger.info("JWT 유효성 확인 완료");
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
logger.info("잘못된 JWT 서명입니다.");
Expand All @@ -117,4 +126,4 @@ public boolean validateToken(String token) {
return false;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.zonebug.debugging.security.user;

import com.zonebug.debugging.domain.user.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

@Data
public class CustomUserDetails implements UserDetails {

private User user;

public CustomUserDetails(User user) {
this.user = user;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_USER";
}
});
return collection;
}

@Override
public String getPassword() {
return user.getPassword();
}

@Override
public String getUsername() {
return user.getEmail();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zonebug.debugging.service;
package com.zonebug.debugging.security.user;

import com.zonebug.debugging.domain.user.User;
import com.zonebug.debugging.domain.user.UserRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.zonebug.debugging.util;
package com.zonebug.debugging.security.util;

import com.zonebug.debugging.domain.user.User;
import com.zonebug.debugging.security.user.CustomUserDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Optional;

Expand All @@ -14,23 +15,21 @@ public class SecurityUtil {

private SecurityUtil() { }

public static Optional<String> getCurrentUsername() {
public static Optional<User> getCurrentUser() {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if(authentication == null) {
logger.debug("Security Context에 인증 정보 없음");
return Optional.empty();
}

String email = null;
if(authentication.getPrincipal() instanceof UserDetails) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
email = userDetails.getUsername();
} else if(authentication.getPrincipal() instanceof String) {
email = (String) authentication.getPrincipal();
User currentUser = null;
if(authentication.getPrincipal() instanceof CustomUserDetails) {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
currentUser = userDetails.getUser();
}

return Optional.ofNullable(email);
return Optional.ofNullable(currentUser);
}

}
Loading