-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- GitHub로 로그인하기 버튼을 누르면 사용자 정보를 요청하는 페이지가 나온다 - 사용자가 정보 제공하기(인증)를 수락하면 다시 메인 페이지로 돌아간다 - 토큰은 저장하지 않고 유저 정보는 저장한다 - 유저 정보가 중복을 저장되지 않도록 방어로직을 구현했다
- Loading branch information
Showing
10 changed files
with
263 additions
and
18 deletions.
There are no files selected for viewing
11 changes: 0 additions & 11 deletions
11
BE/src/main/java/com/codesquad/issuetracker/common/CommonMessage.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
BE/src/main/java/com/codesquad/issuetracker/oauth/controller/GitHubController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.codesquad.issuetracker.oauth.controller; | ||
|
||
import com.codesquad.issuetracker.oauth.service.GitHubOauthService; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import javax.websocket.server.PathParam; | ||
import java.io.IOException; | ||
|
||
@RestController | ||
public class GitHubController { | ||
private static final Logger logger = LoggerFactory.getLogger(GitHubController.class); | ||
|
||
public static final String REDIRECT_URL = "http://localhost:8080"; | ||
|
||
private final GitHubOauthService gitHubOauthService; | ||
|
||
public GitHubController(GitHubOauthService gitHubOauthService) { | ||
this.gitHubOauthService = gitHubOauthService; | ||
} | ||
|
||
@GetMapping("/login/oauth") | ||
public void login(@PathParam("code") String code, HttpServletRequest request, HttpServletResponse response) throws IOException { | ||
logger.info("##### code: {}", code); | ||
gitHubOauthService.login( request, response, REDIRECT_URL, code); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
BE/src/main/java/com/codesquad/issuetracker/oauth/domain/GitHubTokenInfo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.codesquad.issuetracker.oauth.domain; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class GitHubTokenInfo { | ||
@JsonProperty("access_token") | ||
private String accessToken; | ||
@JsonProperty("token_type") | ||
private String tokenType; | ||
@JsonProperty("scope") | ||
private String scope; | ||
|
||
public String getAccessToken() { | ||
return accessToken; | ||
} | ||
|
||
public void setAccessToken(String accessToken) { | ||
this.accessToken = accessToken; | ||
} | ||
|
||
public String getTokenType() { | ||
return tokenType; | ||
} | ||
|
||
public void setTokenType(String tokenType) { | ||
this.tokenType = tokenType; | ||
} | ||
|
||
public String getScope() { | ||
return scope; | ||
} | ||
|
||
public void setScope(String scope) { | ||
this.scope = scope; | ||
} | ||
|
||
public String getAuthorization() { | ||
return this.getTokenType() + " : " + this.getAccessToken(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "AccessTokenResponseSuccess{" + | ||
"accessToken='" + accessToken + '\'' + | ||
", tokenType='" + tokenType + '\'' + | ||
", scope='" + scope + '\'' + | ||
'}'; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
BE/src/main/java/com/codesquad/issuetracker/oauth/service/GitHubOauthService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.codesquad.issuetracker.oauth.service; | ||
|
||
import com.codesquad.issuetracker.oauth.domain.GitHubTokenInfo; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
|
||
public interface GitHubOauthService { | ||
|
||
GitHubTokenInfo getAccessToken(String code); | ||
|
||
void login(HttpServletRequest request, HttpServletResponse response, String url, String authorizationCode) throws IOException; | ||
|
||
void getUserData(HttpServletRequest request, HttpServletResponse response, String url, String accessToken); | ||
|
||
void sendUserCookies(HttpServletResponse response, String jwt, String url) throws IOException; | ||
} |
127 changes: 127 additions & 0 deletions
127
BE/src/main/java/com/codesquad/issuetracker/oauth/service/GitHubOauthServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.codesquad.issuetracker.oauth.service; | ||
|
||
import com.codesquad.issuetracker.config.jwt.hamill.JwtService; | ||
import com.codesquad.issuetracker.hamill.domain.User; | ||
import com.codesquad.issuetracker.hamill.service.UserService_Hamill; | ||
import com.codesquad.issuetracker.oauth.dao.TokenDao; | ||
|
||
import com.codesquad.issuetracker.oauth.domain.GitHubTokenInfo; | ||
import com.codesquad.issuetracker.oauth.domain.Token; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.util.LinkedMultiValueMap; | ||
import org.springframework.util.MultiValueMap; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
import org.springframework.web.client.HttpServerErrorException; | ||
import org.springframework.web.client.RestTemplate; | ||
import org.springframework.web.util.UriComponents; | ||
import org.springframework.web.util.UriComponentsBuilder; | ||
|
||
import javax.servlet.http.Cookie; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.sql.SQLException; | ||
import java.sql.SQLIntegrityConstraintViolationException; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
|
||
@Service | ||
public class GitHubOauthServiceImpl implements GitHubOauthService { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(GitHubOauthServiceImpl.class); | ||
|
||
public static final String GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token"; | ||
public static final String GITHUB_USER_INFO_ACCESS_URL = "https://api.github.com/user"; | ||
|
||
private final TokenDao tokenDao; | ||
private final UserService_Hamill userService_hamill; | ||
private final JwtService jwtService; | ||
|
||
@Value("${github.client_id}") | ||
private String clientId; | ||
@Value("${github.client_secret}") | ||
private String clientSecret; | ||
|
||
public GitHubOauthServiceImpl(TokenDao tokenDao, UserService_Hamill userService_hamill, JwtService jwtService) { | ||
this.tokenDao = tokenDao; | ||
this.userService_hamill = userService_hamill; | ||
this.jwtService = jwtService; | ||
} | ||
|
||
public GitHubTokenInfo getAccessToken(String code) { | ||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); | ||
Map<String, String> header = new HashMap<>(); | ||
header.put("Accept", "application/json"); | ||
headers.setAll(header); | ||
|
||
MultiValueMap<String, String> bodies = new LinkedMultiValueMap<>(); | ||
Map<String, String> body = new HashMap<>(); | ||
body.put("client_id", clientId); | ||
body.put("client_secret", clientSecret); | ||
body.put("code", code); | ||
bodies.setAll(body); | ||
|
||
HttpEntity<?> request = new HttpEntity<>(bodies, headers); | ||
ResponseEntity<?> response = new RestTemplate().postForEntity(GITHUB_ACCESS_TOKEN_URL, request, GitHubTokenInfo.class); | ||
return (GitHubTokenInfo) response.getBody(); | ||
} | ||
|
||
@Override | ||
public void login(HttpServletRequest request, HttpServletResponse response, String url, String authorizationCode) throws IOException { | ||
GitHubTokenInfo gitHubTokenInfo = getAccessToken(authorizationCode); | ||
logger.info("##### Access Token Type: {}, Access Token: {}",gitHubTokenInfo.getTokenType(), gitHubTokenInfo.getAccessToken()); | ||
this.getUserData(request, response, url, gitHubTokenInfo.getAccessToken()); | ||
} | ||
|
||
public void getUserData(HttpServletRequest request, HttpServletResponse response, String url, String accessToken) { | ||
try { | ||
RestTemplate restTemplate = new RestTemplate(); | ||
|
||
HttpHeaders header = new HttpHeaders(); | ||
HttpEntity<?> entity = new HttpEntity<>(header); | ||
|
||
UriComponents sendAccessTokenUrl = UriComponentsBuilder.fromHttpUrl( | ||
GITHUB_USER_INFO_ACCESS_URL + "?access_token=" + accessToken).build(); | ||
|
||
// 이 한줄의 코드로 API를 호출해 MAP 타입으로 전달 받는다 | ||
ResponseEntity<Map> resultMap = restTemplate.exchange(sendAccessTokenUrl.toString(), HttpMethod.GET, entity, Map.class); | ||
|
||
// 유저 정보가 없을 때만 유저 정보를 저장한다 | ||
if (!userService_hamill.existUserByEmail(Objects.requireNonNull(resultMap.getBody()).get("email").toString())) { | ||
userService_hamill.save( | ||
(Objects.requireNonNull(resultMap.getBody())).get("name").toString(), | ||
resultMap.getBody().get("email").toString(), | ||
Long.parseLong(resultMap.getBody().get("id").toString()), | ||
resultMap.getBody().get("avatar_url").toString()); | ||
} | ||
|
||
// 필요한 정보를 담아 JWT 토큰을 만든다 | ||
String jwt = jwtService.makeJwt( | ||
Long.parseLong(resultMap.getBody().get("id").toString()), | ||
resultMap.getBody().get("name").toString(), | ||
resultMap.getBody().get("avatar_url").toString()); | ||
this.sendUserCookies(response, jwt, url); | ||
|
||
} catch (HttpClientErrorException | HttpServerErrorException e) { | ||
logger.info("##### HttpErrorException: {}", e.getMessage()); | ||
} catch (Exception e) { | ||
logger.info("##### Exception: {}", e.getMessage()); | ||
} | ||
} | ||
|
||
public void sendUserCookies(HttpServletResponse response, String jwt, String url) throws IOException { | ||
Cookie cookie = new Cookie("token", jwt); | ||
response.addCookie(cookie); | ||
response.sendRedirect(url); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# Hamill | ||
github.client_id=c8a6d38c880c3ee02abe | ||
github.client_secret=0ff79bb3b1a324b9f759eb70618ac14587212729 | ||
github.client_id=2963f5a20a4e0180d1f6 | ||
github.client_secret=2382bff998d2bd15f26750cfd2e44e98fa24d554 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Client</title> | ||
</head> | ||
<body> | ||
<h3>로그인테스트</h3> | ||
<script> | ||
githubAuthorizationUrl = "https://github.com/login/oauth/authorize?client_id=2963f5a20a4e0180d1f6&scope=user%20public_repo"; | ||
</script> | ||
<button type="button" onclick="location.href=githubAuthorizationUrl">Github으로 로그인하기</button> | ||
</body> | ||
</html> |