이 내용은 RFC7231 문서에서 확인한 내용이다. 실제로 Client 의 device 와 관련된 정보를 파악하기에는 추천되지 않는다. Microsoft 문서에서도 User-Agent 를 사용자의 client 정보를 확인하는데 사용하지 말 것을 추천한다.
The User-Agent (Section 5.5.3), Via (Section 5.7.1 of [RFC7230]), and Server (Section 7.4.2) header fields often reveal information about the respective sender's software systems. In theory, this can make it easier for an attacker to exploit known security holes; in practice, attackers tend to try all potential holes regardless of the apparent software versions being used.
Proxies that serve as a portal through a network firewall ought to take special precautions regarding the transfer of header information that might identify hosts behind the firewall. The Via header field allows intermediaries to replace sensitive machine names with pseudonyms.
User-Agent 에서 수집하는 정보는 다음과 같다.
•
The Device: The hardware that was used.
◦
사용한 hardware 정보.
•
The Operating System: The base software that runs on the hardware
◦
Hardware 가 동작하는 OS 정보.
•
The Layout Engine: The underlying core that converts the ‘HTML’ into a visual/interactive
◦
HTML이 보여지고, 상호작용하는 Layout engine.
•
The Agent: The actual “Browser” that was used.
◦
실제로 사용한 Browser 정보.
•
Extra fields: In some cases we have additional fields to describe the agent. These fields are among others specific fields for the Facebook and Kobo apps, and fields to describe deliberate useragent manipulation situations (Anonymization, Hackers, etc.)
◦
추가 필드, 이 필드에 Facebook 이나 Kakao 같은 app 이름이 나오기도 한다.
◦
특정 앱에서는 여기에 판단할 정보를 추가하기도 한다.
이와 같은 정보를 수집하는 HTTP header 이다.
하지만 이 정보들이 항상 있다고 확신할 수는 없다.
RFC에 규칙은 명시되어 있지만, 이 규칙을 따르지 않는 경우가 많다.
위 정보를 바탕으로 Mobile, Tablet, Desktop, etc. 를 찾아내야 한다. (app 사용 여부는 추가된 문자열로 파악이 더 간단하다)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
User-agent 를 확인한 나의 맥북이 ARM(M1) 맥북이지만, Intel 이라고 반환된다.
예시
구분이 가능한 경우
1.
iPhone
2.
iPad
3.
Android (phone)
4.
Macintosh
5.
Linux
6.
user agent 에 tablet 이 들어간 경우
다음의 경우는 구분이 다소 불분명함
중복을 제거한 6537ea user agent 에 대하여
1.
Windows → desktop, tablet, 게임 콘솔 종류 등등 (약 500개)
•
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; Tablet PC 2.0; moasigns=1.0.45)
◦
이렇게 Tablet 이 명시되어 있다면 다행이지만, 그렇지 않은 경우도 있다.
2.
Android → mobile, tablet 구분이 어려움 (약 5000개)
•
Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
•
mobile 인 경우 Mobile Safari 와 같이 Mobile 이 prefix 로 붙지만, samsung 의 경우 그렇지 않다
◦
Samsung 은 tablet 임에도 Mobile Safari 라는 값이 붙는다
Mobile, Desktop
→ app, web, tablet → app, web
Search
제안
1.
Mobile OS, Device 상위 이름(i.e. iPhone, Android, BlackBerry etc.)이 user-agent에 있을경우 Mobile로 분류한다
2.
device 이름이 iPad 이면 tablet 으로 분류한다
3.
OS가 Windows 인 user-agent의 경우, "Tablet" 문자열이 없다면, desktop 으로 간주한다
4.
OS가 Windows 인 user-agent의 경우 "Tablet" 문자열이 있다면, Tablet 으로 간주한다
5.
Android 이고, Tablet 이라고 명시된 경우만 Tablet 으로 간주한다
6.
Android 이고, Tablet 이라고 명시되지 않으면 Mobile로 분류한다
7.
OS가 Windows(Windows NT), Macintosh, Linux 이면 Desktop 으로 분류한다
8.
user-agent 에 Application 임을 명시하는 문자열이 있고, Tablet 문자열이 없으면 Mobile App 으로 분류한다
9.
user-agent 에 Application 임을 명시하는 문자열과, Tablet 으로 구분하는 문자열이 있다면 Tablet App 으로 분류한다
10.
위의 로직에서 구분되지 않는 경우는 Others 로 분류한다
•
Xbox, Nintendo, car 등등
현재 로직
mobile user agent regex 검색시 결과 참조
1.
Tablet
(iPad|tablet|Tablet|Kindle|Tab|Galaxy Tab)
Kotlin
복사
•
userAgent, device 에 위와 같은 이름이 있는가?
2.
Mobile
(Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune|Lumia)
Kotlin
복사
•
device, os 에 위와 같은 이름이 있는가?
3.
desktop
(Macintosh|Windows|Linux)
Kotlin
복사
•
하지만 이 안에 Xbox, Nintendo 등이 있으면 어떻게 될까...?
•
우리 history 에는 없음
그런데 이런걸 어느정도 해결해주는 Library 가 존재한다.
import ua_parser.Parser;
import ua_parser.Client;
...
String uaString = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3";
Parser uaParser = new Parser();
Client c = uaParser.parse(uaString);
System.out.println(c.userAgent.family); // => "Mobile Safari"
System.out.println(c.userAgent.major); // => "5"
System.out.println(c.userAgent.minor); // => "1"
System.out.println(c.os.family); // => "iOS"
System.out.println(c.os.major); // => "5"
System.out.println(c.os.minor); // => "1"
System.out.println(c.device.family); // => "iPhone"
Java
복사
Sample code
이 Library 를 통해서 1차로 필터링 하고 여기서 undefined 를 받게 되면 그때 위에서 명시한 regex 로 한번 더 확인을 한다.