feat(user-service): Oauth 로그인시 token생성
Oauth 로그인시 response header에 access token, refresh token을 담아 보냄.
This commit is contained in:
@@ -3,6 +3,5 @@ package com.justpickup.userservice.domain.jwt.service;
|
||||
import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
||||
|
||||
public interface RefreshTokenService {
|
||||
void updateRefreshToken(Long id, String refreshToken);
|
||||
JwtTokenDto refreshJwtToken(String accessToken, String refreshToken);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ import com.justpickup.userservice.domain.user.repository.UserRepository;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -21,17 +25,11 @@ import java.util.stream.Collectors;
|
||||
@Transactional(readOnly = true)
|
||||
@Slf4j
|
||||
public class RefreshTokenServiceImpl implements RefreshTokenService {
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final UserRepository userRepository;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateRefreshToken(Long id, String refreshToken) {
|
||||
User user = userRepository.findById(id)
|
||||
.orElseThrow(() -> new NotExistUserException("사용자 고유번호 : " + id + "는 없는 사용자입니다."));
|
||||
|
||||
user.changeRefreshToken(refreshToken);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -56,7 +54,7 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
||||
", refreshToken = " + refreshToken);
|
||||
}
|
||||
|
||||
Authentication authentication = jwtTokenProvider.getAuthentication(user.getEmail());
|
||||
Authentication authentication = getAuthentication(user.getEmail());
|
||||
List<String> roles = authentication.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
|
||||
@@ -70,4 +68,10 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
||||
.refreshToken(newRefreshToken)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Authentication getAuthentication(String email) {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,12 +16,9 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtTokenProvider {
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
@Value("${token.access-expired-time}")
|
||||
private long ACCESS_EXPIRED_TIME;
|
||||
|
||||
@@ -60,10 +57,7 @@ public class JwtTokenProvider {
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Authentication getAuthentication(String email) {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
|
||||
public String getUserId(String token) {
|
||||
try {
|
||||
|
||||
@@ -16,9 +16,9 @@ public class Customer extends User {
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AuthType oauthType;
|
||||
|
||||
|
||||
public Customer(String email, String password, String name, String phoneNumber, AuthType oauthType) {
|
||||
super(email, password, name, phoneNumber,Role.USER);
|
||||
super(email, password, name, phoneNumber,null);
|
||||
this.dtype = Customer.class.getSimpleName();
|
||||
this.oauthType = oauthType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.justpickup.userservice.domain.user.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum Role {
|
||||
GUEST("ROLE_GUEST", "손님"),
|
||||
USER("ROLE_USER", "일반 사용자");
|
||||
|
||||
private final String key;
|
||||
private final String title;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import javax.persistence.*;
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@DiscriminatorColumn(name = "DTYPE")
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class User extends BaseEntity {
|
||||
public abstract class User extends BaseEntity {
|
||||
|
||||
@Id @GeneratedValue
|
||||
@Column(name = "user_id")
|
||||
@@ -28,19 +28,8 @@ public class User extends BaseEntity {
|
||||
|
||||
private String refreshTokenId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Role role;
|
||||
|
||||
@Column(insertable = false,updatable = false)
|
||||
private String dtype;
|
||||
|
||||
public User(String email, String password, String name, String phoneNumber, Role role) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.name = name;
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.role = role;
|
||||
}
|
||||
protected String dtype;
|
||||
|
||||
public User(String email, String password, String name, String phoneNumber, String refreshTokenId) {
|
||||
this.email = email;
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.justpickup.userservice.domain.user.dto.StoreOwnerDto;
|
||||
import com.justpickup.userservice.domain.user.entity.StoreOwner;
|
||||
|
||||
public interface UserService extends OAuth2UserService<OAuth2UserRequest, OAuth2User> {
|
||||
|
||||
void updateRefreshToken(Long id, String refreshToken);
|
||||
CustomerDto findCustomerByUserId(Long userId);
|
||||
StoreOwner saveStoreOwner(StoreOwnerDto storeOwnerDto);
|
||||
}
|
||||
|
||||
@@ -1,60 +1,54 @@
|
||||
package com.justpickup.userservice.domain.user.service;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.domain.user.dto.CustomerDto;
|
||||
import com.justpickup.userservice.domain.user.dto.OAuthAttributeDto;
|
||||
import com.justpickup.userservice.domain.user.dto.StoreOwnerDto;
|
||||
import com.justpickup.userservice.domain.user.dto.OAuthAttributeDto;
|
||||
import com.justpickup.userservice.domain.user.dto.OAuthAttributeDto;
|
||||
import com.justpickup.userservice.domain.user.entity.Customer;
|
||||
import com.justpickup.userservice.domain.user.entity.StoreOwner;
|
||||
import com.justpickup.userservice.domain.user.entity.User;
|
||||
import com.justpickup.userservice.domain.user.exception.NotExistUserException;
|
||||
import com.justpickup.userservice.domain.user.repository.CustomerRepository;
|
||||
import lombok.*;
|
||||
import com.justpickup.userservice.domain.user.repository.UserRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
|
||||
@Slf4j
|
||||
public class UserServiceImpl implements UserService, UserDetailsService {
|
||||
|
||||
private final CustomerRepository customerRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
private final HttpServletResponse response;
|
||||
private final Environment env;
|
||||
private final HttpServletRequest request;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
@@ -85,31 +79,11 @@ public class UserServiceImpl implements UserService, UserDetailsService {
|
||||
return userRepository.save(storeOwner);
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class AuthResponse{
|
||||
private String id;
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
static class AuthRequest {
|
||||
private String code;
|
||||
private String client_id;
|
||||
private String client_secret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
@Transactional
|
||||
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
|
||||
OAuth2UserService<OAuth2UserRequest,OAuth2User> delegate = new DefaultOAuth2UserService();
|
||||
OAuth2User oAuth2User = delegate.loadUser(userRequest);
|
||||
@@ -124,28 +98,53 @@ public class UserServiceImpl implements UserService, UserDetailsService {
|
||||
// OAuth2UserService
|
||||
OAuthAttributeDto attributeDto = OAuthAttributeDto.of(registrationId, userNameAttributeName,oAuth2User.getAttributes());
|
||||
|
||||
Customer customer = customerRepository.save(
|
||||
customerRepository.findByEmail(attributeDto.getEmail())
|
||||
.orElse(attributeDto.toEntity(attributeDto))
|
||||
);
|
||||
|
||||
Customer customer = saveCustomer(attributeDto);
|
||||
|
||||
|
||||
// TODO: 2022/02/16 Response에 token 담아 보내기
|
||||
|
||||
String userEmail = customer.getEmail();
|
||||
|
||||
|
||||
Collection<? extends GrantedAuthority> authorities = loadUserByUsername(userEmail).getAuthorities();
|
||||
List<String> roles = authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
|
||||
String accessToken = jwtTokenProvider.createJwtAccessToken(userEmail, request.getRequestURI(), roles);
|
||||
String refreshToken = jwtTokenProvider.createJwtRefreshToken();
|
||||
|
||||
updateRefreshToken(customer.getId(), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
||||
|
||||
customer.changeRefreshToken(refreshToken);
|
||||
|
||||
response.setHeader("Access-token",accessToken);
|
||||
response.setHeader("refresh-token",refreshToken);
|
||||
|
||||
|
||||
|
||||
return new DefaultOAuth2User(
|
||||
Collections.singleton(new SimpleGrantedAuthority(customer.getRole().getKey()))
|
||||
authorities
|
||||
, attributeDto.getAttributes()
|
||||
, attributeDto.getNameAttributeKey());
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class UserPayload implements Serializable {
|
||||
private String name;
|
||||
private String email;
|
||||
|
||||
public UserPayload(Customer user){
|
||||
this.name = user.getName();
|
||||
this.email = user.getEmail();
|
||||
}
|
||||
@Transactional
|
||||
public Customer saveCustomer(OAuthAttributeDto attributeDto){
|
||||
return customerRepository.save(
|
||||
customerRepository.findByEmail(attributeDto.getEmail())
|
||||
.orElse(attributeDto.toEntity(attributeDto))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateRefreshToken(Long id, String refreshToken) {
|
||||
User user = userRepository.findById(id)
|
||||
.orElseThrow(() -> new NotExistUserException("사용자 고유번호 : " + id + "는 없는 사용자입니다."));
|
||||
|
||||
user.changeRefreshToken(refreshToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.justpickup.userservice.global.security;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.domain.user.service.UserService;
|
||||
import com.justpickup.userservice.global.dto.LoginRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -31,7 +32,7 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
||||
private final UserService userService;
|
||||
|
||||
// login 리퀘스트 패스로 오는 요청을 판단
|
||||
@Override
|
||||
@@ -67,7 +68,7 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
String accessToken = jwtTokenProvider.createJwtAccessToken(userId, request.getRequestURI(), roles);
|
||||
String refreshToken = jwtTokenProvider.createJwtRefreshToken();
|
||||
|
||||
refreshTokenServiceImpl.updateRefreshToken(Long.valueOf(userId), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
||||
userService.updateRefreshToken(Long.valueOf(userId), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
||||
|
||||
Map<String, String> tokens = Map.of(
|
||||
"access_token", accessToken,
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.domain.user.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
@@ -19,10 +20,10 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@@ -34,7 +35,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
LoginAuthenticationFilter loginAuthenticationFilter =
|
||||
new LoginAuthenticationFilter(authenticationManagerBean(), jwtTokenProvider, refreshTokenServiceImpl);
|
||||
new LoginAuthenticationFilter(authenticationManagerBean()
|
||||
,applicationContext.getBean(JwtTokenProvider.class)
|
||||
,applicationContext.getBean(UserService.class));
|
||||
|
||||
loginAuthenticationFilter.setFilterProcessesUrl("/login");
|
||||
|
||||
http.csrf().disable();
|
||||
|
||||
Reference in New Issue
Block a user