4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

네이버 쇼핑 최저가 리스트 만들기

르무엘 2023. 3. 21. 14:50

네이버 쇼핑 최저가 저장

유투브 시연

https://www.youtube.com/watch?v=6OemCC6xQdw&t=54s 

깃 소스 저장

https://github.com/MyoungSoo7/shopping_lowprice

 

GitHub - MyoungSoo7/shopping_lowprice: 자바11, 스프링부트2.7, 그래들, h2, mysql, springsecurity, spring data jpa

자바11, 스프링부트2.7, 그래들, h2, mysql, springsecurity, spring data jpa - GitHub - MyoungSoo7/shopping_lowprice: 자바11, 스프링부트2.7, 그래들, h2, mysql, springsecurity, spring data jpa

github.com

(인텔리제이, 자바11, 스프링부트2.7, 그래들,타임리프, 스피링시큐리티,mysql ,h2database)

jwt 설정

 

package com.sparta.springcore.security;

import com.sparta.springcore.security.filter.FormLoginFilter;
import com.sparta.springcore.security.filter.JwtAuthFilter;
import com.sparta.springcore.security.jwt.HeaderTokenExtractor;
import com.sparta.springcore.security.provider.FormLoginAuthProvider;
import com.sparta.springcore.security.provider.JWTAuthProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
@EnableGlobalMethodSecurity(securedEnabled = true) // @Secured 어노테이션 활성화
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final JWTAuthProvider jwtAuthProvider;
    private final HeaderTokenExtractor headerTokenExtractor;

    public WebSecurityConfig(

            JWTAuthProvider jwtAuthProvider,
            HeaderTokenExtractor headerTokenExtractor
    ) {
        this.jwtAuthProvider = jwtAuthProvider;
        this.headerTokenExtractor = headerTokenExtractor;
    }

    @Bean
    public BCryptPasswordEncoder encodePassword() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth
                .authenticationProvider(formLoginAuthProvider())
                .authenticationProvider(jwtAuthProvider);
    }

    @Override
    public void configure(WebSecurity web) {
        // h2-console 사용에 대한 허용 (CSRF, FrameOptions 무시)
        web
                .ignoring()
                .antMatchers("/h2-console/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        // 서버에서 인증은 JWT로 인증하기 때문에 Session의 생성을 막습니다.
        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

/*
         * 1.
         * UsernamePasswordAuthenticationFilter 이전에 FormLoginFilter, JwtFilter 를 등록합니다.
         * FormLoginFilter : 로그인 인증을 실시합니다.
         * JwtFilter       : 서버에 접근시 JWT 확인 후 인증을 실시합니다.
         */
        http
                .addFilterBefore(formLoginFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);

        http.authorizeRequests()
                .anyRequest()
                .permitAll()
                .and()
                // [로그아웃 기능]
                .logout()
                // 로그아웃 요청 처리 URL
                .logoutUrl("/user/logout")
                .permitAll()
                .and()
                .exceptionHandling()
                // "접근 불가" 페이지 URL 설정
                .accessDeniedPage("/forbidden.html");
    }

    @Bean
    public FormLoginFilter formLoginFilter() throws Exception {
        FormLoginFilter formLoginFilter = new FormLoginFilter(authenticationManager());
        formLoginFilter.setFilterProcessesUrl("/user/login");
        formLoginFilter.setAuthenticationSuccessHandler(formLoginSuccessHandler());
        formLoginFilter.afterPropertiesSet();
        return formLoginFilter;
    }

    @Bean
    public FormLoginSuccessHandler formLoginSuccessHandler() {
        return new FormLoginSuccessHandler();
    }

    @Bean
    public FormLoginAuthProvider formLoginAuthProvider() {
        return new FormLoginAuthProvider(encodePassword());
    }

    private JwtAuthFilter jwtFilter() throws Exception {
        List<String> skipPathList = new ArrayList<>();

        // Static 정보 접근 허용
        skipPathList.add("GET,/images/**");
        skipPathList.add("GET,/css/**");

        // h2-console 허용
        skipPathList.add("GET,/h2-console/**");
        skipPathList.add("POST,/h2-console/**");
        // 회원 관리 API 허용
        skipPathList.add("GET,/user/**");
        skipPathList.add("POST,/user/signup");

        skipPathList.add("GET,/");
        skipPathList.add("GET,/basic.js");

        skipPathList.add("GET,/favicon.ico");

        FilterSkipMatcher matcher = new FilterSkipMatcher(
                skipPathList,
                "/**"
        );

        JwtAuthFilter filter = new JwtAuthFilter(
                matcher,
                headerTokenExtractor
        );
        filter.setAuthenticationManager(super.authenticationManagerBean());

        return filter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

최저가 쇼핑 리스트

 

10개 패키지 ( 2개 테스트용)

aop : 부가기능( api 사용시간)

controller : api, folder. home, itemsearch, product, user, username 제어 7개

dto (data transfer object) : foler, item, kakaouserinfo, productMyPriceRequest , productRequest, SingupRequestDto

exception : 예외( Error, RestAPIException )

model (DB테이블 역할 7개) : ApiUseTime, Folder, Product ,Timestamped, UserName, UserRoleENum, Users 

repository : DB 연결 역할 5개( apiusetime, folder, product, username, user)

sercurity ( 사용자 보안)

 

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
@EnableGlobalMethodSecurity(securedEnabled = true) // @Secured 어노테이션 활성화
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder encodePassword() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(WebSecurity web) {
        // h2-console 사용에 대한 허용 (CSRF, FrameOptions 무시)
        web
                .ignoring()
                .antMatchers("/h2-console/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        http.authorizeRequests()
                // image 폴더를 login 없이 허용
                .antMatchers("/images/**").permitAll()
                // css 폴더를 login 없이 허용
                .antMatchers("/css/**").permitAll()
                // 회원 관리 처리 API 전부를 login 없이 허용
                .antMatchers("/user/**").permitAll()
                // 그 외 어떤 요청이든 '인증'
                .anyRequest().authenticated()
                .and()
                    // [로그인 기능]
                    .formLogin()
                    // 로그인 View 제공 (GET /user/login)
                    .loginPage("/user/login")
                    // 로그인 처리 (POST /user/login)
                    .loginProcessingUrl("/user/login")
                    // 로그인 처리 후 성공 시 URL
                    .defaultSuccessUrl("/")
                    // 로그인 처리 후 실패 시 URL
                    .failureUrl("/user/login?error")
                    .permitAll()
                .and()
                    // [로그아웃 기능]
                    .logout()
                    // 로그아웃 요청 처리 URL
                    .logoutUrl("/user/logout")
                    .permitAll()
                    .and()
                    .exceptionHandling()
                    // "접근 불가" 페이지 URL 설정
                    .accessDeniedPage("/forbidden.html");
    }
}

service : folder, itemsearch, kakaouser, product , username, user 6개

utils : 스케줄러

validator : 유효성체크 (product ,url)

 

테이블 구조 7개

 

 

회원가입 시작

 

가입후 로그인

 

로그인 화면

네이버 쇼핑 API로 레스트빈 불러오기

 

 

` 를 이용해서 입력값을 query 파라미터로 검색해 옵니다.

RestTemplate을 사용하여

HttpEntity에  body,hearder 담아서=>[ body(String)와  HttpHeards(네이버클라이언트id,secret) 담아서 보내고(exchange)]

ResponseEntity<String>으로 받아옵니다.

 
  // 네이버 쇼핑 API 호출에 필요한 Header, Body 정리
        RestTemplate rest = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("X-Naver-Client-Id", "");
        headers.add("X-Naver-Client-Secret", "");
        String body = "";
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        // 네이버 쇼핑 API 호출 결과 -> naverApiResponseJson (JSON 형태)
        ResponseEntity<String> responseEntity
        = rest.exchange("https://openapi.naver.com/v1/search/shop.json?query=" + query,
        HttpMethod.GET, requestEntity, String.class);
        String naverApiResponseJson = responseEntity.getBody();

 ResponseEntity의 body 만 String 타입으로 받으면

아이템 목록이 나옵니다.

String naverApiResponseJson = responseEntity.getBody();
 

 

해당 String 을 우리에게 필요한 데이터만 추출해서 return 합니다.

 

저장하면 하기와 같이 나옵니다.

폴더 추가 및 폴더에 아이템을 추가 할 수 있다.

폴더는 해당 유저에 한하여 폴더추가 시키고

또 아이템은 해당유저의 폴더에 한하여 추가한다.

 

관리자 회원가입시 관리자는 특정패스워드 입

 

관리자는 모든 사용자의 쇼핑목록을 볼수 있다.

 

 

LIST