<script type="text/javascript">
$("#input").on("keyup",function(e){
if(e.keyCode==13) {
alert("엔터키 이벤트");
}
});
</script>
분류 전체보기
- JQuery 엔터키(Enter) 이벤트 2022.12.06
- [C#] NICE API 본인인증 소스 및 정리 2022.11.08 2
- DataTable에 대한 LINQ 쿼리 2022.08.23
- bcrypt 패스워드 암호화 처리 2022.07.25
- TypeError: Router.use() requires a middleware function but got a Object 2022.07.21
JQuery 엔터키(Enter) 이벤트
[C#] NICE API 본인인증 소스 및 정리
사내 업무 중 NICE에서 제공해주는 본인인증 서비스를 적용해야 하는 상황이 있었다.
API 개발가이드는 JAVA 언어 기반으로만 예시코드를 제공해주는 상황으로
C# 소스 적용 시, 암호화 처리 후 잘 되었는지 JAVA 코드라 비교해야 하는 작업까지 진행하였다.
아래는 API 처리 흐름도와 C# 소스이다.
본인인증 API 처리 흐름도
(1) 기관 인증 토큰 API 최초 1회 호출 반영구적(50년)
(2) 1번 ‘기관 인증 토큰’으로 NICE 본인확인 호출을 위한 암호화 토큰 API 호출
(3) 2번에서 발급받은 암호화 토큰으로 대칭키(Symmetric Key, IV)와 무결성키(hmac Key)를 생성
(4) 요청할 데이터(request_data)를 대칭키로 암호화 하고 암호화 데이터를 체크
→ 요청 데이터 암호화는 AES128/CBC/PKCS7 패딩 후, Base64 Encoding으로 사용
(5) 생성한 데이터를 form에 추가하여 전송
(6) return URL 을 통해 받은 암호화를 복호화 처리
‘기관 인증 토큰 API 호출’ 과 ’암호화 Token 요청 API’
총 2번의 API를 호출하고 암호화 키를 생성하여
데이터를 암호화 처리해서 본인인증 폼 레이어를 호출하는 방식이다.
각 API 전송 시 필요한 데이터는 아래 사이트에서 신청한 아이디로 로그인 한 후
MyAppList > 상세보기에서 필요한 데이터 값을 조회 할 수 있다
사이트 URL : https://www.niceapi.co.kr/#/
string __niceClientID = 사이트에서 제공해주는 값;
string __niceClientSecret = 사이트에서 제공해주는 값;
#region [ 최초 50년(반영구적) Token 생성 / 토큰 만료 시 처리 ]
public string GetNiceApiAccessToken()
{
string hostName = "https://svc.niceapi.co.kr:22001";
string requestUrl = "/digital/niceid/oauth/oauth/token";
string postData = "grant_type=client_credentials&scope=default";
byte[] sendData = UTF8Encoding.UTF8.GetBytes(postData);
string url = hostName + requestUrl;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.ContentLength = sendData.Length;
string text = __niceClientID + ":" + __niceClientSecret;
byte[] byteUTF8 = Encoding.UTF8.GetBytes(text);
string base64UTF8 = Convert.ToBase64String(byteUTF8);
request.Headers.Add("Authorization", "Basic " + base64UTF8);
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(sendData, 0, sendData.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string rawData = responseStream.ReadToEnd();
parser = new JsonTextParser();
JObject obj = JObject.Parse(rawData);
JToken jToken = obj["dataBody"];
accessToken = jToken.SelectToken("access_token").ToString();
message = rawData;
return "OK";
}
catch (System.Exception ex)
{
message = ex.Message.ToString();
return ex.Message.ToString();
}
}
#endregion
string __accessToken = 인증 기관 토큰 (위 소스에서 부여받은 값);
string __productID = 사이트에서 제공해주는 값;
#region [ 암호화 토큰 발급 ]
private string GetNiceApiEncryptToken()
{
string hostName = "https://svc.niceapi.co.kr:22001";
string requestUrl = "/digital/niceid/api/v1.0/common/crypto/token";
string url = hostName + requestUrl;
req_dtim = DateTime.Now.ToString("yyyyMMddHHmmss");
req_no = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
double unixTimeStamp = DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
string text = __accessToken + ":" + (int)unixTimeStamp + ":" + __niceClientID;
byte[] byteUTF8 = Encoding.UTF8.GetBytes(text);
string base64UTF8 = Convert.ToBase64String(byteUTF8);
request.Headers.Add("Authorization", "bearer " + base64UTF8);
request.Headers.Add("client_id", client_id);
request.Headers.Add("productID", productID);
request.ContentType = "application/json";
request.Method = "POST";
var streamWriter = new StreamWriter(request.GetRequestStream());
try
{
string strData = "{\"dataHeader\": {\"CNTY_CD\":\"ko\"}, \"dataBody\":{\"req_dtim\":\"" + req_dtim + "\",\"req_no\":\"" + req_no + "\",\"enc_mode\":\"1\"}}";
JObject jsonData = JObject.Parse(strData);
streamWriter.Write(strData);
streamWriter.Flush();
streamWriter.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string rawData = responseStream.ReadToEnd();
JsonTextParser parser = new JsonTextParser();
JObject obj = JObject.Parse(rawData);
JToken jToken = obj["databody"];
string token_val = jToken.SelectToken("token_val").ToString();
string token_version_id = jToken.SelectToken("token_version_id").ToString();
string siteCode = jToken.SelectToken("site_code").ToString();
JToken jTokenHeader = obj["dataHeader"];
resultCode = jTokenHeader.SelectToken("GW_RSLT_CD").ToString();
// 성공시 키 발급 처리
if (resultCode 성공시)
{
// 대칭키
string strValue = req_dtim.Trim() + req_no.Trim() + token_val.Trim();
SHA256Managed sha256 = new SHA256Managed();
byte[] encryptBytes = sha256.ComputeHash(Encoding.ASCII.GetBytes(strValue));
string strKeyValue = Convert.ToBase64String(encryptBytes);
// 대칭키(Symmetric Key, IV), 무결성 키 생성
string sKey = strKeyValue.Substring(0, 16);
string IV = strKeyValue.Substring(strKeyValue.Length - 16);
string encryptedHMacKey = strKeyValue.Substring(0, 32);
string strRequestNo = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
string strRequestData = "{\"requestno\":\"" + strRequestNo + "\",\"returnurl\":\"" + HttpContext.Current.Request.Url.AbsoluteUri + "\",\"sitecode\":\"" + siteCode + "\",\"methodtype\":\"post\",\"popupyn\":\"Y\"}";
try
{
RijndaelManaged rijndaeManaged = new RijndaelManaged();
rijndaeManaged.Mode = CipherMode.CBC;
rijndaeManaged.Padding = PaddingMode.PKCS7;
rijndaeManaged.Key = Encoding.ASCII.GetBytes(sKey);
rijndaeManaged.IV = Encoding.ASCII.GetBytes(IV);
byte[] encDataByte = EncryptStringToBytes(strRequestData, rijndaeManaged.Key, rijndaeManaged.IV);
enc_data = Convert.ToBase64String(encDataByte);
byte[] hmacKeyByte = Encoding.UTF8.GetBytes(encryptedHMacKey);
HMACSHA256 sha = new HMACSHA256(hmacKeyByte);
byte[] integrityValueByte = sha.ComputeHash(Encoding.ASCII.GetBytes(enc_data));
integrity_value = Convert.ToBase64String(integrityValueByte);
}
catch (System.Exception ex)
{
message = ex.Message.ToString();
return ex.Message.ToString();
}
}
return "";
}
catch (System.Exception ex)
{
message = ex.Message.ToString();
return ex.Message.ToString();
}
}
#endregion
#region [ Byte를 EncryptString으로 변환 ]
protected byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
#endregion
'프로그래밍 > TIL' 카테고리의 다른 글
DevOps란 무엇인가? (0) | 2022.07.20 |
---|
DataTable에 대한 LINQ 쿼리
1. 확장 메서드란 무엇인가
확장 메서드는 C# 3.0 부터 추가된 기능으로 이미 정의된 형식에 사용자 정의 함수를 확장시키는 작업을 수행하는 메서드이다.
간단하게 클래스에 손을 대지 않고 메서드를 추가할 수 있는 방법이라 보면 된다.
2. 확장 메서드 선언하는 방법
(1) static 한정자로 메서드 선언
(2) 해당 메서드의 첫 번째 매개 변수는 반드시 this 키워드와 함께 확장하고자 하는 클래스(형식) 의 인스턴스여야 한다.
확장 메서드 생성/호출 예제 #문자열 공백 카운트
확장 메서드 생성
public static class ExtenstionString { public static int GetSpaceCount(this String str) { if(!string.isNullOrEmpty(str)) { string[] spaceArray = str.Split(" "); return spaceArray.Length - 1; } else { return 0; } } }
기본 클래스인 String 클래스를 활용하여 확장 메서드 호출
class Program { static void Main(string[] args) { string str = "ABC DEL GHI JKL"; Console.WriteLine(str.GetSpaceCount()); } } [실행결과] 3
정리하자면 확장 메서드란 기존 형식의 코드 변경 없이 사용자 임의로 만든 메서드를 대상 형식에 추가 할 수 있도록 도와주는 메서드이다.
1. LINQ란 무엇인가
LINQ란 Language Integrate Query의 약자로 통합 질의 언어이다,
기존의 Query는 Database의 데이터를 다루기 위해 사용된 언어이지만, LINQ는 컬렉션 형태로 되어있는 모든 데이터에 대해 질의를 할 수 있는 기술이다.
즉, MS-SQL 등 DB 데이터를 가져오는데 LINQ를 사용할 수 있는 것은 물론이고, 메모리상의 컬렉션 또는 XML에 대해서도 LINQ를 사용할 수 있다.
2. LINQ와 확장 메서드 관계
확장 메서드 LINQ에서 쿼리를 위한 메서드 Select, Where 등은 확장 메서드로 되어 있기 때문이다.
Aggregate, All, Any 등 파란색 화살표가 아래방향으로 향하는 것이 확장 메서드이다.
LINQ에서는 이처럼 많은 수의 확장 메서드를 사용한다.
3. Lambda Expression (람다 표현식)
익명 대리자, 무명 메서드를 좀 더 실용적으로 만든 것으로, 컴파일 과정에서 Delegate로 치환된다.
(매개변수들) => (표현식)
// **홀수** 출력 람다 표현식
// 컴파일 시 1,2번은 3번과 같이 Anonymous Delegate 형태
int[] numbers = {1,2,3,4,5,6,7,8,9}
1. IEnumerable<int> odds = numbers.Where(x=> x%2 == 1);
2. IEnumerable<int> odds = numbers.Where((int x) => x%2 == 1);
3. IEnumerable<int> odds = numbers.Where(delegate(int x) { return x%2 ==1; });
1. DataTable에서 확장 메서드 & LINQ & 람다를 활용
DataTable 에 LINQ 쿼리를 수행하려고 할 때, LINQ 쿼리는 DataTable, DataTable Row에 허용이 되지 않는다.
// #1) 회원 아이디가 "kmmun" 인 DataRow 조회
DataTable dt = biz.[SP명]
dt.Where(x => x["MemID"].ToString() == "kmmun"); // DataTable에 접근이 되지 않는다.
dt.Rows[0].Where(x => x["MemID"].ToString() == "kmmun"); // DataRow에 접근이 되지 않는다.
AsEnumerable() EnumerableRowCollection 을 활용하여 LINQ 쿼리 작성
public static EnumerableRowCollection<DataRow> AsEnumerable(this DataTable source);
DataTable dt = biz.[SP명]
dt.AsEnumerable().Where(x => x["MemID"].ToString() == "kmmun");
2. DataTable 형 변환, Null 체크
AsEnumerable() 행 컬렉션 LINQ 쿼리 후, CopyToDataTable()를 활용하여 DataTable로 형 변환 할 수 있다. 단, Where() 문 등 조건 이후 LINQ 쿼리 결과가 없을 수 있어 Row 개수를 체크 해준 후 CopyToDataTable() 해줘야한다.
DataTable dt = biz.[SP명]
int rowCnt = dt.AsEnumerable().Where(x => x["MemID"].ToString() == "kmmun").Count()
if(rowCnt > 0)
{
dt = dt.AsEnumerable().Where(x => x["MemID"].ToString() == "kmmun").CopyToDataTable();
}
참조
'프로그래밍 > C#' 카테고리의 다른 글
DateTime 형식 ToString()으로 변환 시 문자열 처리 (0) | 2020.12.18 |
---|---|
Delegate (0) | 2020.03.22 |
bcrypt 패스워드 암호화 처리
1. bcrypt 패스워드 암호화 처리
npm i bcrypt //bcrypt 설치
회원 가입 함수 호출 시 패스워드 암호화 처리
const bcrypt = require(’bcrypt’)
router.post('/', async(req, res, next) => {
try{
const hash = await bcrypt.hash(req.body.password, 10);
// 이미 회원가입여부 체크
const isUser = await db.User.findOne({
where:{
email:req.body.email
},
if(isUser){
// 중략
}
const newUser = await db.User.create({
email: req.body.email,
password: hash, // HASH 암호화 된 패스워드 저장
nickname: req.body.nickname
});
} catch (err) {
console.log(error);
}
});
'프로그래밍 > NodeJS' 카테고리의 다른 글
TypeError: Router.use() requires a middleware function but got a Object (0) | 2022.07.21 |
---|
TypeError: Router.use() requires a middleware function but got a Object
TypeError: Router.use() requires a middleware function but got a Object
const express= require('express');
const router = express.Router();
router.use('/getboardlist', require('./getboardlist'));
router.use('/addboard', require('./addboard'));
routes 폴더 파일 내 위와 같이
module.exports=router
를 작성하지 않아 발생하는 에러이다.
const express= require('express');
const router = express.Router();
router.use('/getboardlist', require('./getboardlist'));
router.use('/addboard', require('./addboard'));
module.exports = router;
'프로그래밍 > NodeJS' 카테고리의 다른 글
bcrypt 패스워드 암호화 처리 (0) | 2022.07.25 |
---|