인증과 권한

조현재·2023년 2월 1일
0

MSA

목록 보기
11/17

Login 모델 생성

@Data
public class RequestLogin {
   @Email
   @NotNull(message = "이메일은 빈칸이 안됩니다.")
   @Size(min = 2, message = "이메일은 두글자 이상 입력해주세요")
   private String email;
   @NotNull(message = "비밀번호는 빈칸이 안됩니다.")
   @Size(min = 8, message = "비밀번호는 8글자 이상 입력해주세요")
   private String password;
}

UsernamePasswordAuthenticationFilter 상속 class 생성

@Slf4j
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private UserService userService;
    private Environment env;

    public AuthenticationFilter(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

    public AuthenticationFilter(AuthenticationManager authenticationManager, UserService userService, Environment env) {
        super.setAuthenticationManager(authenticationManager);
        this.userService = userService;
        this.env = env;
    }


    //로그인 요청을 보냈을 때 로직
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        try {
            RequestLogin creds = new ObjectMapper().readValue(request.getInputStream(), RequestLogin.class);

            //인증정보 생성
            return getAuthenticationManager()
                    .authenticate(
                            new UsernamePasswordAuthenticationToken(
                                    creds.getEmail(),       //id
                                    creds.getPassword(),    //pw
                                    new ArrayList<>()       //권한 정보
                            )
                    );

        } catch(IOException e){
            throw new RuntimeException(e);
        }
    }

    //로그인 성공했을 때 로직
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        log.debug(((User)authResult.getPrincipal()).getUsername());

    }

security의 UsernamePasswordAuthenticationFilter를 구현하여 로그인 요청을 보냈을 때와 로그인을 성공 했을 때 로직을 정의한다.

Security 설정

5.7.X 부터 WebSecurityConfigurerAdapter Deprecate가 Deprecate 되었다.

@Configuration //다른 bean들 보다 우선순위를 앞으로
@RequiredArgsConstructor
@EnableWebSecurity //security 어노테이션
public class WebSecurity {

    private final UserService userService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final Environment env; //패스워드를 암호화할떄 jwt토큰 유효시간 다양한 yml파일 정보를 가져올때 쓰기 위해 등록


    @Bean // resource 에 대해 Spring Security FilterChain 제외
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/h2-console/**", "/favicon.ico");
    }

    //권한
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        AuthenticationManager authenticationManager = getAuthenticationFilter(http);

        http.csrf().disable();
        http.authorizeRequests()
		.antMatchers("/error/**").permitAll()
		.and()
        .authenticationManager(authenticationManager) 
        .addFilter(getAuthenticationFilter(authenticationManager));

        // //h2 console error 해결을 위해
        http.headers().frameOptions().disable();

        return http.build();
    
        private AuthenticationManager getAuthenticationFilter(HttpSecurity http) throws Exception {
        	AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        	authenticationManagerBuilder.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
        		return authenticationManagerBuilder.build();
    }

    	private AuthenticationFilter getAuthenticationFilter(AuthenticationManager authenticationManager) {
        	return new AuthenticationFilter(authenticationManager, userService, env);
    }

기존의 모두 permit()해주던 코드에서 filter를 통해 거르도록 설정을 변경해 주었다. 여기서 중요한 것은 마지막 인증 코드인데. UserDetailsService를 상속받은 userSerivce가 필요하다.

public interface UserService extends UserDetailsService {
    
}
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity userEntity = userRepository.findByEmail(username);
        if (userEntity == null) {
            throw new UsernameNotFoundException(username);
        }
        return new User(username, userEntity.getEncryptedPwd(),
                true, true, true, true,
                new ArrayList<>());
    }

우리가 지정한 email 로그인 방식에 따라 email로 회원을 검색 후 User 객체를 반환하도록 코드를 작성했다.

gateway설정
yaml

        - 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를 붙일 필요 없어진다
controller에서 @RequestMapping("/") 로 변경

profile
내일이 다른

0개의 댓글