KJB 소스 정리
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
package com.eactive.eai.authserver.custom;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.eactive.eai.adapter.http.dynamic.UnkownMessageLogUtils;
|
||||
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
|
||||
import com.eactive.eai.authserver.config.RequestContextData;
|
||||
import com.eactive.eai.authserver.dao.TokenIssuanceLogDAO;
|
||||
import com.eactive.eai.authserver.service.OAuth2Manager;
|
||||
import com.eactive.eai.authserver.util.BeanUtils;
|
||||
import com.eactive.eai.authserver.vo.ClientVO;
|
||||
import com.eactive.eai.common.dao.DAOException;
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.util.MessageUtil;
|
||||
import com.eactive.eai.common.util.UUID;
|
||||
import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@Controller
|
||||
public class DJBOAuth2Controller {
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
private static final String HEADER_TRACEID = "traceId";
|
||||
private static final String SERVICE_CODE_ACCESS_TOKEN = "00";
|
||||
|
||||
@Autowired
|
||||
private TokenIssuanceLogDAO tokenIssuanceLogDAO;
|
||||
|
||||
@RequestMapping(value = { "/dj/oauth/token", "/dj/oauth2/token" }, method = RequestMethod.POST,
|
||||
consumes = "application/json", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenJson(@RequestBody DJBOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
@RequestMapping(value = { "/dj/oauth/token", "/dj/oauth2/token" }, method = RequestMethod.POST,
|
||||
consumes = "application/x-www-form-urlencoded", produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenForm(@RequestParam Map<String, String> params,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
DJBOAuth2AccessTokenRequest tokenRequest = new DJBOAuth2AccessTokenRequest();
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
tokenRequest.setScope(params.get("scope"));
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
@GetMapping(value = { "/dj/oauth/token", "/dj/oauth2/token" }, produces = "application/json; charset=UTF-8")
|
||||
@ResponseBody
|
||||
public ResponseEntity<?> tokenGet(@RequestParam Map<String, String> params,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
DJBOAuth2AccessTokenRequest tokenRequest = new DJBOAuth2AccessTokenRequest();
|
||||
tokenRequest.setGrantType(params.get("grant_type"));
|
||||
tokenRequest.setClientId(params.get("client_id"));
|
||||
tokenRequest.setClientSecret(params.get("client_secret"));
|
||||
tokenRequest.setScope(params.get("scope"));
|
||||
return issueToken(tokenRequest, request, response);
|
||||
}
|
||||
|
||||
private ResponseEntity<?> issueToken(DJBOAuth2AccessTokenRequest tokenRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(tokenRequest.toString());
|
||||
}
|
||||
|
||||
RequestContextData data = new RequestContextData();
|
||||
data.setClientId(tokenRequest.getClientId());
|
||||
data.setIpAddress(extractIpAddress(request));
|
||||
data.setGrantType(tokenRequest.getGrantType());
|
||||
data.setScope(tokenRequest.getScope());
|
||||
data.setUsername("none");
|
||||
data.setResource("none");
|
||||
RequestContextData.ThreadLocalRequestContext.set(data);
|
||||
|
||||
String grantType = tokenRequest.getGrantType();
|
||||
String clientId = tokenRequest.getClientId();
|
||||
String clientSecret = tokenRequest.getClientSecret();
|
||||
String scopes = tokenRequest.getScope();
|
||||
|
||||
try {
|
||||
if (!StringUtils.equals(grantType, "client_credentials")) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {grant_type}");
|
||||
}
|
||||
|
||||
String[] scopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(scopes, " ");
|
||||
Set<String> scopeSet = new HashSet<>();
|
||||
for (String scope : scopeArr) {
|
||||
scopeSet.add(scope);
|
||||
}
|
||||
|
||||
ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
|
||||
verifyClient(clientDetails, clientId, clientSecret, scopeSet);
|
||||
|
||||
String traceId = UUID.randomUUID().toString().replace("-", "");
|
||||
response.setHeader(HEADER_TRACEID, traceId);
|
||||
|
||||
HashMap<String, String> authorizationParameters = new HashMap<>();
|
||||
authorizationParameters.put(OAuth2Utils.GRANT_TYPE, grantType);
|
||||
authorizationParameters.put(OAuth2Utils.CLIENT_ID, clientId);
|
||||
authorizationParameters.put("client_secret", clientSecret);
|
||||
|
||||
Set<String> responseType = new HashSet<>();
|
||||
responseType.add(grantType);
|
||||
|
||||
OAuth2Request authorizationRequest = new OAuth2Request(authorizationParameters, clientId, null, true,
|
||||
scopeSet, null, "", responseType, null);
|
||||
|
||||
Principal principal = new OAuth2Authentication(authorizationRequest, null);
|
||||
ResponseEntity<OAuth2AccessToken> result = tokenEndpoint().postAccessToken(principal, authorizationParameters);
|
||||
OAuth2AccessToken token = result.getBody();
|
||||
|
||||
DJBOAuth2AccessTokenResponse responseToken = new DJBOAuth2AccessTokenResponse();
|
||||
responseToken.setAccessToken(token.getValue());
|
||||
responseToken.setTokenType(token.getTokenType());
|
||||
responseToken.setExpiresIn(Long.valueOf(token.getExpiresIn()));
|
||||
responseToken.setScope(StringUtils.join(token.getScope(), " "));
|
||||
responseToken.setJti((String) token.getAdditionalInformation().get("jti"));
|
||||
responseToken.setClientId((String) token.getAdditionalInformation().get("client_id"));
|
||||
|
||||
//logTokenIssuance(true, false, "Token issued successfully", token.getValue());
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return ResponseEntity.ok(mapper.writeValueAsString(responseToken));
|
||||
|
||||
} catch (JwtAuthException e) {
|
||||
logger.info("Token request[/dj/oauth2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e.getMessage());
|
||||
logTokenIssuance(false, false, e.getMessage(), null);
|
||||
|
||||
Properties logProp = new Properties();
|
||||
logProp.put("clientId", clientId);
|
||||
UnkownMessageLogUtils.logUnkownMessage(this.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
tokenRequest.toString(), logProp, request, response, "RECEAIIRP301", e);
|
||||
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AUTH_FAIL, e.getMessage());
|
||||
int statusCode = NumberUtils.toInt(StringUtils.left(e.getCode(), 3), HttpStatus.UNAUTHORIZED.value());
|
||||
return ResponseEntity.status(statusCode).body(errorJson);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.info("Token request[/dj/oauth2/token] => clientId: {}, grantType: {}, scope: {}",
|
||||
clientId, grantType, scopes);
|
||||
logger.error(e.getMessage());
|
||||
logTokenIssuance(false, false, e.getMessage(), null);
|
||||
|
||||
Properties logProp = new Properties();
|
||||
logProp.put("clientId", clientId);
|
||||
UnkownMessageLogUtils.logUnkownMessage(this.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
tokenRequest.toString(), logProp, request, response, "RECEAIIRP301", e);
|
||||
|
||||
String errorJson = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AUTH_FAIL, "Unauthorized. [Unknown]");
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorJson);
|
||||
|
||||
} finally {
|
||||
RequestContextData.ThreadLocalRequestContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyClient(ClientDetails clientDetails, String clientId, String clientSecret, Set<String> scopeSet)
|
||||
throws JwtAuthException {
|
||||
|
||||
if (StringUtils.isBlank(clientId)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {client_id}");
|
||||
}
|
||||
if (clientDetails == null) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [client not found]");
|
||||
}
|
||||
if (StringUtils.isBlank(clientSecret)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {client_secret}");
|
||||
}
|
||||
if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Bad client credentials(Client Secret is not match)]");
|
||||
}
|
||||
if (scopeSet.isEmpty()) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"),
|
||||
"Invalid Mandatory Field {scope}");
|
||||
}
|
||||
if (!clientDetails.getScope().containsAll(scopeSet)) {
|
||||
throw new JwtAuthException(
|
||||
String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"),
|
||||
"Unauthorized. [Bad client credentials(Include unacceptable scope)]");
|
||||
}
|
||||
}
|
||||
|
||||
private String extractIpAddress(HttpServletRequest request) {
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) ip = request.getHeader("Proxy-Client-IP");
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) ip = request.getRemoteAddr();
|
||||
return ip;
|
||||
}
|
||||
|
||||
private TokenEndpoint tokenEndpoint() {
|
||||
return BeanUtils.getBean("tokenEndpoint", TokenEndpoint.class);
|
||||
}
|
||||
|
||||
private void logTokenIssuance(boolean isSuccess, boolean isRestrictionExempt, String resultMessage, String accessToken) {
|
||||
try {
|
||||
if (!EAIDBLogControl.isEnable()) {
|
||||
logger.warn("DB logging is disabled. Skipping token issuance logging.");
|
||||
return;
|
||||
}
|
||||
RequestContextData data = RequestContextData.ThreadLocalRequestContext.get();
|
||||
|
||||
TokenIssuanceLog log = new TokenIssuanceLog();
|
||||
String clientId = data.getClientId();
|
||||
log.setClientId(clientId);
|
||||
|
||||
if (StringUtils.isNotBlank(clientId)) {
|
||||
try {
|
||||
ClientVO clientVO = OAuth2Manager.getInstance().getClientInfo(clientId);
|
||||
log.setAppName(clientVO.getClientName());
|
||||
log.setOrgId(clientVO.getOrgId());
|
||||
log.setOrgName(clientVO.getOrgName());
|
||||
} catch (DAOException e) {
|
||||
logger.warn("cannot find clientVO - " + clientId);
|
||||
}
|
||||
}
|
||||
|
||||
log.setGrantType(data.getGrantType());
|
||||
log.setScope(data.getScope());
|
||||
log.setIpAddress(data.getIpAddress());
|
||||
log.setSuccessYn(isSuccess ? "Y" : "N");
|
||||
log.setIssuanceDateTime(LocalDateTime.now());
|
||||
log.setRestrictionExemptYn(isRestrictionExempt ? "Y" : "N");
|
||||
log.setResultMessage(resultMessage);
|
||||
log.setAccessToken(accessToken);
|
||||
|
||||
tokenIssuanceLogDAO.saveTokenIssuanceLog(log);
|
||||
} catch (Throwable th) {
|
||||
logger.error("Error while logging token issuance: " + th.getMessage(), th);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user