POST
{ContextPath}/user-service/login
// JSON
{
"email" : "jsieon@naver.com",
"password" : "test1234"
}
// RequestLogin.java
@Data
public class RequestLogin {
@NotNull(message = "Email cannot be null")
@Size(min = 2, message = "Email not be less than 2 characters")
@Email
private String email;
@NotNull(message = "Password cannot be null")
@Size(min = 8, message = "Password must be equals or greater than 8 characters")
private String password;
}
// AuthenticationFilter.java
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
private UserService userService;
private Environment env;
public AuthenticationFilter(AuthenticationManager authenticationManager,
UserService userService,
Environment env) {
this.userService = userService;
this.env = env;
super.setAuthenticationManager(authenticationManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
RequestLogin creds = new ObjectMapper().readValue(request.getInputStream(), RequestLogin.class);
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
new ArrayList<>()
);
// AuthenticationManager 인증 작업 요청
// email과 password를 spring security에 사용할 수 있는 형태로 바꾼다
return getAuthenticationManager().authenticate(authRequest);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
...
}
// WebSecurity.java
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurity {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final Environment env;
AuthenticationManager authenticationManager;
// spring.boot 2.7 부터는 WebSecurityConfigurerAdapter가 아닌
// SecurityFilterChain 을 사용 합니다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
authenticationManager = authenticationManagerBuilder.build();
//AuthenticationFilter authenticationFilter = new AuthenticationFilter();
//authenticationFilter.setAuthenticationManager(authenticationManager);
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager , userService , env);
http.csrf().disable();
http.authorizeRequests()
//.antMatchers("/error/**").permitAll() // public abstract java.lang.String javax.servlet.ServletRequest.getRemoteAddr() is not supported 보기 싫을때 활성화
.antMatchers("/**")
.hasIpAddress("127.0.0.1")
.and()
.authenticationManager(authenticationManager)
.addFilter(authenticationFilter)
;
http.headers().frameOptions().disable();
return http.build();
}
//ex) 기존의 경우 AuthenticationManagerBuilder 를 오버라이드 하여 사용 하였지만 filterChain 안에서 호출 하여 설정 합니다.
/*
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
}
*/
//ex)filter를 authenticationAmanger에 주입 하던 getAuthenticationFilter역시 filterChain 내부에서 사용 합니다.
/*
private AuthenticationFilter getAuthenticationFilter() throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter();
authenticationFilter.setAuthenticationManager(authenticationManager);
return authenticationFilter;
}
*/
}
참고
https://www.inflearn.com/chats/789887/spring-boot-2-7-%EC%9D%B4%EC%83%81%EC%9D%84-%EC%82%AC%EC%9A%A9-%ED%95%98%EC%8B%9C%EB%8A%94-%EB%B6%84%EC%9D%98-%EA%B2%BD%EC%9A%B0 (SpringBoot 2.7이상 사용시)
// UserService.java
public interface UserService extends UserDetailsService {
UserDto createUser(UserDto userDto);
UserDto getUserByUserId(String userId);
Iterable<UserEntity> getUserByAll();
}
// UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserEntity userEntity = userRepository.findByEmail(username);
if (userEntity == null) {
throw new UsernameNotFoundException(username);
}
return new User(userEntity.getEmail(),
userEntity.getEncryptedPwd(),
true,
true,
true,
true,
new ArrayList<>());
}
// application.yml
...
spring:
application:
name: gateway-service
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway GlobalFilter
preLogger: true
postLogger: true
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user-service/login
- Method=POST
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user-service/(?<segment>.*), /$\{segment}
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user-service/users
- Method=POST
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user-service/(?<segment>.*), /$\{segment}
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user-service/**
- Method=GET
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user-service/(?<segment>.*), /$\{segment}
/user-service/(?<segment>.*)
를 /$\{segment}
로 Rewrite해준다./user-service/users
-> /users
200 OK를 반환하는 것을 볼 수 있다.