다오의 개발일지

[Spaceplorer.com] 소셜 로그인-1 3/6 본문

프로젝트

[Spaceplorer.com] 소셜 로그인-1 3/6

다오__ 2024. 3. 7. 00:55

2024.03.04 - [프로젝트] - [Spaceplorer.com] 웹 프로젝트 개요 3/4-

 

[Spaceplorer.com] 웹 프로젝트 아이디어 및 기획 3/4~

글 요약 이름 : Spaceplorer 개요 : 여러 행성 간 여행을 도와주는 패키지여행안내 및 판매 서비스 개발툴 : 개발환경 : 인텔리제이 개발언어 : 자바, 자바스크립트 프레임워크 : 스프링부트, 부트스

dao-blog.tistory.com


가장 먼저 API 문서를 작성했다. 회원 기능개발을 해야하기 떄문에, 회원 관련 부분만 API를 만들었다.

회원기능을 마무리 한 후, Swagger를 사용해보려고 한다.

 

최근 웹사이트들을 참조해보면 새로운 회원가입 기능을 만들기 보단 소셜로그인을 위주로 만들기 때문기도 하고 보안측면과 접근성을 따져봤을 때, 소셜로그인으로 회원 가입하는게 좋겠다고 생각했다. 우선 카카오와 네이버를 먼저 만들고 다음에 구글을 만들 생각이다.

 

소셜 로그인

스프링 시큐리티를 이용해 인증 및 인가를 진행한다.

https://dao-blog.tistory.com/88

 

스프링 시큐리티 인증 및 인가 spring security

스프링 시큐리티 스프링 시큐리티는 자바 및 자바 EE 기반의 웹 애플리케이션을 위한 보안 프레임워크로, 주로 인증과 권한 부여 등의 보안 관련 기능을 제공한다. 개발 과정에서 보안은 많은 시

dao-blog.tistory.com

 

소셜 서버에서 받은 엑세스토큰은 클라이언트에게 헤더로 전달하고, 리프레시토큰은 레디스에 저장하려고 한다. 엑세스 토큰으로 소셜서버에서 유저정보를 받아오고, 리프레시토큰을 통해 엑세스토큰을 갱신한다. 

 

 

계속 소셜로그인을 추가할 것을 생각하여 Auth 인터페이스를 만들었다.

public interface Auth {

    //예를들어, 네이버필터의 requestUri는 /api/auth/naver/login
    // request가 requestUri와 일치하는지 판별
    static boolean requestMatch(String requestUri, HttpServletRequest request){
        return new AntPathRequestMatcher(requestUri).matches(request);
    }

    String getAuthorizationRequestUrl();

}

requestMatch는 로그인 버튼을 눌렀을 때 요청한 uri와 필터에 정의한 uri를 비교한다. 맞으면 일치한 filter의 로직이 동작한다.

 

Auth 구현 객체를 만들기 전에 비교하여 filter를 동작시켜야 하므로 static을 사용했다.

 

이를 구현한 NaverAuth, KakaoAuth를 만들었다.

@Slf4j
@RequiredArgsConstructor
@Getter
@ToString
public class NaverAuth implements Auth {

    private final String clientId;
    private final String redirectUri;
    private final String responseType;
    private final String scope;
    private final String authorizationUrl;
    private final String AUTHORIZATION_REQUEST_URL_FORMAT_NAVER = "%s?client_id=%s&redirect_uri=%s&response_type=%s&scope=%s";


    public String getAuthorizationRequestUrl(){

        String authorizationRequestUrl = String.format(AUTHORIZATION_REQUEST_URL_FORMAT_NAVER,
                authorizationUrl, clientId, redirectUri, responseType, scope);

        log.info("method=getAuthorizationRequestUrl, authorizationRequestUrl={}",authorizationRequestUrl);
        return authorizationRequestUrl;
    }
}

 

getAuthorizationRequestUrl()는 필드들을 조합해 Authorization server에 접근하는 url을 만들어서 리턴한다.

 

 

//네이버 Authorization server 접근
@RequiredArgsConstructor
@Slf4j
public class AuthNaverLoginFilter extends GenericFilterBean {

    private final String REQUEST_NAVER_URI = "/api/auth/naver/login";
    private final String AUTHORIZATION_NAVER_URL = "https://authorization-server.com/oauth/authorize";
    private final String CLIENT_ID = "your-client-id";
    private final String REDIRECT_URI = "localhost:8080/login/oauth2/code/custom";
    private final String RESPONSE_TYPE = "code";
    private final String SCOPE = "read_profile";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        //Authorization url 얻기
        if(Auth.requestMatch(REQUEST_NAVER_URI,request)){
            Auth auth = new NaverAuth(CLIENT_ID, REDIRECT_URI, RESPONSE_TYPE, SCOPE, AUTHORIZATION_NAVER_URL);
            log.info("method=doFilter, auth={}",auth);

            String authorizationRequestUri = auth.getAuthorizationRequestUrl();

            return;
            /*response.sendRedirect(authorizationRequestUri);*/
        }

        chain.doFilter(request, response);
    }
}

네이버 로그인 필터이다. Authorization server에 접근하기 위한 데이터들을 정리하고, 해당 url로 리다이렉트 시키게끔 하였다.

 

소셜로그인 필터가 계속 추가될 것을 고려해 FilterConfig 클래스를 만들어 관리했다.

@Slf4j
@Configuration
public class FilterConfig {
    @Bean
    public Filter authNaverLoginFilter() {
        return new AuthNaverLoginFilter();
    }

    @Bean
    public Filter authKakaoLoginFilter() {
        return new AuthKakaoLoginFilter();
    }


}

 

중간에 URL 맵핑 핸들러를 만들어서 URL에 맞는 필터가 실행되게끔 만들어봤지만, 로그를 봤을때 모든 필터가 실행되는 것이다. 필터를 실행 안하게끔하는 방법이 있겠지만 핸들러 또한 만들 필요없이 if문으로 처리되게끔 다시 코드를 수정했다.

 

시큐리티 설정 클래스에서 필터체인을 UsernamePasswordAuthenticationFilter의 앞에 실행되게끔 만들었다.

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@Slf4j
public class WebSecurityConfig {

    private final AuthKakaoLoginFilter authKakaoLoginFilter;
    private final AuthNaverLoginFilter authNaverLoginFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws  Exception 
    
        ...
        
        //필터체인 연결
        http
                // 기타 필요한 http 보안 구성
                .addFilterBefore(authKakaoLoginFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(authNaverLoginFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

스프링 시큐리티가 5.7버전 이후부터는 SecurityFilterChain 빈을 생성해 만들어야 함을 알게됬다.

 

 

 

포스트맨으로 테스트 한 결과, 로그가 잘 찍히는 것을 확인했다.

 

024-03-07T00:12:33.991+09:00 DEBUG 8172 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing GET /api/auth/kakao/login
2024-03-07T00:12:33.992+09:00  INFO 8172 --- [nio-8080-exec-5] c.s.s.filter.AuthKakaoLoginFilter        : method=doFilter, auth=KakaoAuth(clientId=your-client-id, redirectUri=localhost:8080/login/oauth2/code/custom, responseType=code, scope=read_profile, authorizationUrl=https://authorization-server.com/oauth/authorize, AUTHORIZATION_REQUEST_URL_FORMAT_KAKAO=%s?client_id=%s&redirect_uri=%s&response_type=%s&scope=%s)
2024-03-07T00:12:33.992+09:00  INFO 8172 --- [nio-8080-exec-5] c.s.spaceplorerweb.auth.KakaoAuth        : method=getAuthorizationRequestUrl, authorizationRequestUrl=https://authorization-server.com/oauth/authorize?client_id=your-client-id&redirect_uri=localhost:8080/login/oauth2/code/custom&response_type=code&scope=read_profile

 

 

 

스프링 시큐리티와 소셜로그인에 대해 학습하다 보니 코딩을 많이 하지 못해 아쉽다. 내일은 소셜로그인과 토큰저장하는 것을 마무리하고, 본격적으로 기능개발에 힘써야겠다. 

 


 

https://yeseongs-organization.gitbook.io/spaceplorer/reference/api/users

 

Users - Spaceplorer

유저에 대한 API 명세입니다.

yeseongs-organization.gitbook.io

https://dao-blog.tistory.com/84

 

[Spaceplorer.com] 웹 프로젝트 아이디어 및 기획 3/4~

글 요약 이름 : Spaceplorer 개요 : 여러 행성 간 여행을 도와주는 패키지여행안내 및 판매 서비스 개발툴 : 개발환경 : 인텔리제이 개발언어 : 자바, 자바스크립트 프레임워크 : 스프링부트, 부트스

dao-blog.tistory.com