-
[Spring Boot] spread sheet 연동하기 2Backend/개발 2021. 7. 23. 22:49반응형
TIL 30일차
[이어지는 글]
2021.07.21 - [TIL] - 29일차 : spreed sheet 연동하기
[필요한 기능]
google drive에 저장되어있는 spread sheet 공유 문서를 읽어와 값 조회하기
[문제]
이전에 구현한 방법은 저장된 토큰이 없을 경우 redirect link에 접속해 구글로그인을 하고, 새로운 credential token을 얻어와 서버에 저장하는 방식이다.
그런데 지금은 사용자마다 뭔가 로그인해서 값을 얻어오는 로직을 겉으로 다 숨겨야할 것 같아서, 프로젝트 자체가 sheet와 연결되는 정도의 구현을 하고싶다. (리다이렉트, 구글 로그인 기능 필요 X)
[해결]
다음 블로그에서 힌트를 찾아서 해결하였다.
https://jsonobject.tistory.com/561
Google auth library oauth2 http
https://github.com/googleapis/google-auth-library-java
<dependency> <groupId>com.google.auth</groupId> <artifactId>google-auth-library-oauth2-http</artifactId> <version>0.27.0</version> </dependency>
// 이번에 사용한 방식 ServiceAccountCredentials serviceCredentials = ServiceAccountCredentials.fromStream(new FileInputStream("src/main/resources/" + SERVICE_ACCOUNT_FILE_PATH)); serviceCredentials = (ServiceAccountCredentials) serviceCredentials.createScoped(Arrays.asList(SheetsScopes.SPREADSHEETS_READONLY));
// 이전 글 방식 GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); // Build flow and trigger user authorization request. GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( new NetHttpTransport(), JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))) .setAccessType("offline") .build(); LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8080).build(); Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
리다이렉트 방식에서 서비스계정 인증방식으로 변경했다.
- 첫번째 방식은 api 사용자 인증정보 - 서비스계정을 생성하고, 그에 해당하는 json파일로 인증한다. spreadsheet에서 서비스계정 이메일을 편집자로 등록하거나, 링크공유를 설정해야한다.
- 두번째 방식은 Oauth 클라이언트 ID 에서 생성한 계정의 credential json파일을 읽어오고, 구글 로그인을 통해서 토큰을 생성하여 인증한다 . (localhost8080/Callback으로 redierct)
참고로 구글링 했을 때 많이 나오는 api.client.googleapis.auth.oauth2 GoogleCredential은 deprecated됐다고 나와서 못쓰는줄 알았는데, 이 라이브러리 (google.auth.ouath2)의 GoogleCredentials을 사용하면 되는것 같다.
오류 목록
FileNoutFoundException
# 단순 파일이 존재하지 않을 경우 java.io.FileNotFoundException: src/main/resources/aaa.json (No such file or directory)
forbidden 403
# 제한된 사용자만 볼 수 있는 파일에 서비스계정을 추가하지 않았을 경우 { "code" : 403, "errors" : [ { "domain" : "global", "message" : "The caller does not have permission", "reason" : "forbidden" } ], "message" : "The caller does not have permission", "status" : "PERMISSION_DENIED" }
링크가 있는 사용자 모두 가능
이때는 서비스계정이 필요하지 않을 것 같아서 서비스계정 없이 기본 credential을 생성해서 접근하는 방식을 찾고있는데 잘 안나온다. defaultCredential함수 써보거나,, 뭔가 하면 googlecredentials request had insufficient authentication scopes 에러뜸
static으로 만든 Utils Class에서는 @Value를 읽어오지 못하는 오류 -> @Component로 해결
// SheetsUtils.class @Component public class SheetsUtils { @Value("${api.google.appName}") private String appName; @Value("${api.google.serviceAccountFile}") private String SERVICE_ACCOUNT_FILE_PATH; private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); public Sheets getSheetsFromServiceAccount() throws GeneralSecurityException, IOException { ServiceAccountCredentials serviceCredentials = ServiceAccountCredentials.fromStream(new FileInputStream("src/main/resources/" + SERVICE_ACCOUNT_FILE_PATH)); serviceCredentials = (ServiceAccountCredentials) serviceCredentials.createScoped(Arrays.asList(SheetsScopes.SPREADSHEETS_READONLY)); Sheets service = new Sheets.Builder( GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, new HttpCredentialsAdapter(serviceCredentials) ).setApplicationName(appName).build(); return service; } } //------------------------------------------------------------------------------------ // Test @Autowired private SheetsUtils sheetsUtils; @Test public void getsheet_service방식() throws GeneralSecurityException, IOException { Sheets sheets = sheetsUtils.getSheetsFromServiceAccount(); assertThat(sheets.getApplicationName()).isEqualTo(appName); }
sheet 연결은 service단에 넣으면 안될 것 같아서 Utils로 따로 빼고 static으로 만들어두고 사용하면 좋을 것 같아서 다 static으로 해놨는데, 그러면
@Value()
를 못읽어온다. 1편에서도 적어놨는데 static변수에는 @value가 injection되지 않기 때문. 그래서 @Component 사용해서 빈으로 등록해서 service 불러오는 방식으로 바꿨다.
이제 구글시트에 있는 내용 정리해서 팀정보 , 경기일정, 결과 가져오는거 구현해야겠다 !!참고 기능
인텔리제이 command+alt+l -> 자동정렬
- ctrl+option+o -> 안쓰는 import 정리
출처
본문에 바로 추가.
'Backend > 개발' 카테고리의 다른 글
[Spring Boot] 참가자 등록 구현, DTO (0) 2021.08.02 [Spring Boot] 경매 프로그램 , 엔티티 설계 (3) 2021.07.28 [Spring Boot] spread sheet 연동하기 (3) 2021.07.21 [Java] 우선순위 큐, Comparable vs Comparator (2) 2021.07.14 [Notion] TIL 1-27일차 (0) 2021.07.14