본문 바로가기
Java/Spring

Spring) Spring Security

by NH_club 2023. 7. 24.
Spring Security
더보기

Spring Security 인증 및 인가에 대해 많은 기능을 지원해주는 Spring 프레임 워크

Spring 에서 모든 호출은 DispatcherServlet을 통과하게 되고 이후에 각 요청을 담당하는 Controller 로 분배된다.이 때, 각 요청에 대해서 공통적으로 처리해야할 필요가 있을 때 DispatcherServlet 이전에 단계가 필요하며 이것이 Filter이다. Security는 기본적으로 세션 방식으로 동작 한다. JWT 방식으로 수정할 수 있다.
@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String url = httpServletRequest.getRequestURI();
        // 이 url은 검사를 하지 않겠다.
        if (StringUtils.hasText(url) &&
                (url.startsWith("/auth") )
        ) {
            log.info("인증 처리를 하지 않는 url" + url);
            // 회원가입, 로그인 관련 API 는 인증 필요없이 요청 진행
            chain.doFilter(request, response); // 다음 Filter 로 이동
        } else { // 아니면 검사를 한다.

            // 나머지 API 요청은 인증 처리 진행
            // 토큰 확인
            String tokenValue = jwtUtil.getJwtFromHeader(httpServletRequest); //헤더에서 JWT뽑아옴 jwtutll에 있는 getJwtFromHeader 이 메서드를 통해 토큰을 뽑아냄

            if (StringUtils.hasText(tokenValue)) { // 토큰이 존재하면 검증 시작
                // JWT 토큰 substring
                String token = jwtUtil.substringToken(tokenValue);

                // 토큰 검증
                if (!jwtUtil.validateToken(token)) {
                    throw new IllegalArgumentException("Token Error");
                }

                // 토큰에서 사용자 정보 가져오기
                Claims info = jwtUtil.getUserInfoFromToken(token);

                //이거 뺴고 실험해보자
                User user = userRepository.findByUserEmail(info.getSubject()).orElseThrow(() ->
                        new NullPointerException("Not Found User")
                );

                request.setAttribute("user", user);
                chain.doFilter(request, response); // 다음 Filter 로 이동
            } else {
                throw new IllegalArgumentException("Not Found Token");
            }
        }
    }

필터로 처리했을 땐 이렇게 길었던 코드가 시큐리티로 처리하면

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF 설정
        // CSRF 를 사용하지 않을 것이기 때문에 disable로 설정
        http.csrf((csrf) -> csrf.disable());
        // filter의 기능과 동일
        http.authorizeHttpRequests((authorizeHttpRequests) ->
                authorizeHttpRequests
                        .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
                        .requestMatchers("/auth/**").permitAll() // "/auth"로 시작하는 모든 url을 접근 허용
                        .anyRequest().authenticated() // 그 외 모든 요청 인증처리
        );

        // 로그인 사용
        http.formLogin(Customizer.withDefaults());

        return http.build();
    }

이렇게 간단하게 인증 인가 처리를 할 수 있다. permitAll 말고도 여러 기능을 제공한다. 역할에 따라 부여할 수도 있음.

Security를 사용하면 Filter는 필요 없다?
더보기

둘이 가지고 있는 목적이 조금 다르다. 

Filter는 서블릿 컨테이너에 의해 관리되는 객체로, 특정 URL 패턴에 대한 요청을 인터셉트(중단)하고 처리하는 기능을 한다. 이를 통해 로깅, 인코딩, 압축 등과 같은 관심사들을 분리하여 처리할 수 있다.

Security는 보안을 위한 프로임 워크로, 인증과 인가, 권한부여 등의 보안 관련 기능을 제공한다.

위 처럼 필터에서 인증 인가 기능을 수행한다면 시큐리티로 대체할 수 있지만, 그 외의 기능을 사용하려면 필터가 필요하다.

UserDetailsService 와 UserDetailsServiceImpl
더보기

Security 인증 과정에서 사용자의 정보를  DB에서 가져오는데 사용된다. 사용자가 로그인 요청을 보낼 때 실행되며 Security 인증 매커니즘에 의해 처리 된다.

Security 인증 매커니즘
세션 방식 vs JWT 방식
더보기

세션 기반 인증은 상태를 서버에서 유지한다.

JWT 기반 인증은 상태를 클라이언트에 저장한다.

세션 기반 인증은 탈취 당할 일이 없지만, 서버에 부하가 JWT 기반 인증에 비해 더하다.

JWT 기반 인증은 부하가 덜하나, 탈취 당할 위험이 있으니 HTTPS 프로토콜로 통신해야하며, Refersh Token을 사용하는 것이 좋다.

'Java > Spring' 카테고리의 다른 글

Spring) 동시성 제어  (0) 2023.08.06
Spring) 테스트 코드 작성하기  (0) 2023.08.03
Spring) refresh token  (0) 2023.07.23
23.07.19) CORS 에러 해결  (0) 2023.07.19
23-07-09) Spring 강의 노트  (0) 2023.07.09