Câu hỏi và trả lời PV hay cho FE Senior/Principal

Câu hỏi và trả lời PV hay cho FE Senior/Principal

 Câu hỏi và trả lời PV hay cho FE Senior/Principal


1) So sánh React và Vue như thế nào? Khi nào chọn React, khi nào chọn Vue?

Mình thường so sánh theo 5 tiêu chí: hệ sinh thái, mức chuẩn hoá, độ linh hoạt kiến trúc, learning curve/team fit, mục tiêu sản phẩm (scale/long-term).

React

  • Ưu: hệ sinh thái cực lớn (Next.js, React Query, TanStack, nhiều UI libs), nhiều lựa chọn kiến trúc; cộng đồng rộng → dễ tuyển; thích hợp sản phẩm scale lớn, multi-team.

  • Nhược: “quá tự do” → nếu thiếu chuẩn hoá dễ loạn (state, data fetching, folder structure, patterns). Hiện nay phải dựa mạnh vào conventions (Next App Router, React Query, ESLint rules, design system…).

Mình chọn React khi:

  • Sản phẩm scale lớn, nhiều squad cùng phát triển, cần “ecosystem leverage” (Next.js, tooling, monitoring, performance tooling).

  • Cần SSR/SSG/ISR mạnh (SEO, landing pages, content-heavy, B2C).

  • Team đã có “React maturity” hoặc cần tuyển nhanh.

Vue (Vue 3)

  • Ưu: framework “batteries included” hơn (router, state Pinia, conventions rõ), DX mượt; Composition API khá mạnh và gọn.

  • Nhược: ecosystem nhỏ hơn React (nhưng vẫn tốt); tuyển dụng tuỳ thị trường.

Mình chọn Vue khi:

  • Team cần onboard nhanh, muốn convention rõ ràng để ít tranh luận.

  • Dự án enterprise/dashboard nội bộ, tốc độ delivery quan trọng.

  • Có sẵn codebase Vue hoặc team core mạnh Vue.

Cách chốt câu phỏng vấn:
“React mạnh về hệ sinh thái và scale multi-team; Vue mạnh về DX và convention giúp team chạy nhanh. Mình chọn dựa trên team fit + nhu cầu SSR/SEO + mức độ chuẩn hoá cần thiết.”


2) Thiết kế kiến trúc frontend dự án lớn? Cấu trúc thư mục và chia module?

Mình đã làm kiến trúc theo hướng domain-driven (feature/module), ưu tiên: dễ scale theo squad, giảm coupling, dễ test và refactor.

Nguyên tắc mình hay dùng

  • Tách theo domain/feature thay vì tách theo “type” (components/pages/utils) quá sớm.

  • Public API cho mỗi module: chỉ export từ index.ts để kiểm soát phụ thuộc.

  • Layer rõ ràng: UI ↔ application ↔ domain ↔ infrastructure.

  • Tránh shared bừa bãi: “shared” chỉ chứa thứ thật sự generic (design system, primitives).

Ví dụ cấu trúc (React/Next hoặc Vue/Nuxt đều áp dụng được)

src/ app/ # routing layer (Next app router / Nuxt pages) modules/ auth/ api/ components/ hooks/ # or composables/ model/ # types, state, selectors services/ pages/ # nếu không dùng file-based routing index.ts billing/ user/ shared/ ui/ # design system components lib/ # helpers, config, constants api/ # http client, interceptors, common DTO assets/ tests/

Chia module như thế nào?

  • Module theo business capability (auth, user, billing, report…).

  • Nếu scale rất lớn: có thể tiến tới micro-frontend (Module Federation / single-spa) nhưng chỉ khi:

    • tổ chức nhiều team độc lập,

    • release cadence khác nhau,

    • và có năng lực vận hành (CI/CD, versioning, shared deps).

Câu chốt:
“Mình ưu tiên module theo domain + public API rõ + dependency rule (module A không import sâu module B). Nhờ vậy dự án lớn vẫn giữ được tính maintainable.”


3) Kinh nghiệm với NextJS/NuxtJS? Khi nào SSR, khi nào CSR?

Kinh nghiệm Next/Nuxt

  • Dùng để tận dụng routing + SSR/SSG/ISR + bundling + optimization.

  • Thực tế mình hay phối:
    SSR/SSG cho trang cần SEO/first load, và CSR cho phần app dashboard.

Khi nào SSR?

  • SEO quan trọng (marketing pages, listing public).

  • Time-to-Content cần nhanh trên mạng yếu.

  • Nội dung phụ thuộc request (auth, geo, personalization) mà vẫn cần HTML render ban đầu.

  • Cần tốt cho share preview, bots, social crawlers.

Khi nào CSR?

  • App kiểu internal tool / dashboard, đăng nhập rồi mới dùng.

  • Dữ liệu realtime, tương tác nhiều, SEO không quan trọng.

  • Muốn giảm tải server render, đơn giản hoá caching SSR.

Bonus: SSG/ISR (nếu bạn muốn ghi điểm)

  • SSG: nội dung ít thay đổi, build ra static.

  • ISR: nội dung thay đổi theo chu kỳ, muốn “static nhưng có refresh”.

Câu chốt:
“Mình chọn SSR/SSG/ISR khi cần SEO + first content; CSR cho ứng dụng nặng tương tác sau login. Với Next/Nuxt mình hay dùng hybrid để tối ưu tổng thể.”


4) State management trong ứng dụng lớn (Redux, Zustand, Pinia, Vuex…)

Mình phân loại state trước, rồi mới chọn tool.

4 loại state mình tách

  1. Server state (data từ API, cache, sync): ưu tiên React Query/TanStack Query (React) hoặc tương đương bên Vue.

  2. UI state cục bộ (modal, toggle, input): dùng useState/ref tại component.

  3. Client global state (auth info, theme, permission, feature flags…): dùng store nhẹ (Zustand/Redux Toolkit hoặc Pinia).

  4. Form state: dùng form libs (React Hook Form / vee-validate…) + schema validation.

Tool lựa chọn

  • Redux Toolkit: khi cần chuẩn hoá nghiêm, debug tốt, middleware, complex workflows.

  • Zustand: nhẹ, ít boilerplate, rất hợp global client state vừa phải.

  • Pinia (Vue): default choice hiện đại, modular, devtools tốt.

  • Vuex: nếu legacy.

Nguyên tắc quan trọng

  • Đừng đưa server state vào Redux/Pinia nếu không cần → dễ phình store, khó cache invalidation.

  • Normalize data khi entity lớn và tái sử dụng nhiều (users, products…).

  • Quy định naming + boundaries: store theo domain, không “global store bự”.

Câu chốt:
“Mình tách server state ra khỏi client state. Server state dùng query-cache; global client state chỉ giữ những thứ thật sự cross-cutting.”


5) Tối ưu performance cho React/Vue có lượng user lớn?

Mình tối ưu theo 3 lớp: rendering, network/data, bundle/runtime, kèm observability.

Rendering / UI

  • Tránh re-render lan truyền:

    • React: memoization đúng chỗ (memo, useMemo, useCallback) nhưng chỉ khi đo thấy cần.

    • Tách component: “smart vs dumb”, hạn chế props drilling hoặc context khiến re-render rộng.

  • Virtualization cho list lớn (react-window/react-virtual; Vue tương đương).

  • Debounce/throttle input search, resize, scroll handlers.

  • Giảm work ở main thread: web worker cho xử lý nặng.

Network / Data

  • Cache & revalidate:

    • Dùng TanStack Query: caching, dedupe request, staleTime, retry.

  • Pagination / infinite scroll thay vì load all.

  • Prefetch route/data cho trang tiếp theo (Next/Nuxt hỗ trợ tốt).

  • HTTP caching / CDN cho assets và API response phù hợp.

Bundle / Runtime

  • Code splitting theo route/feature; lazy load những phần ít dùng (chart lib, editor…).

  • Tree-shaking đúng, tránh import “cả library”.

  • Tối ưu ảnh: responsive images, next/image hoặc nuxt image module.

  • SSR/SSG cho trang public để cải thiện LCP.

Observability (đây là điểm senior hay có)

  • Đặt performance budget (JS size, LCP/INP/CLS).

  • Dùng tooling: Lighthouse, Web Vitals, profiling React DevTools, runtime monitoring (Sentry/Datadog…).

  • Tối ưu dựa trên metrics thật chứ không “tối ưu cảm tính”.

Câu chốt:
“Mình tối ưu theo số đo: Web Vitals + profiling. Ưu tiên giảm work render, tối ưu cache data và chia nhỏ bundle; sau đó mới đến micro-optimizations.”


1) “Anh/chị sử dụng TypeScript ở mức nào? Best practice?”

Mức độ sử dụng (nên nói cụ thể theo các “nấc”):

  • Dùng TS như “contract”: type cho data flow end-to-end (API → domain → UI).

  • Thành thạo generic, utility types (Partial, Pick, Omit, ReturnType, Awaited…), discriminated union, type narrowing, type guards, mapped types.

  • Biết khi nào không nên type quá chặt (tránh type gymnastics làm giảm tốc độ dev).

  • Setup/lint/CI: strict mode, eslint rules cho TS, type-check trong pipeline.

Best practices mình hay áp dụng (nói 6–8 ý là đủ mạnh):

  1. Bật strict (ít nhất: strict, noUncheckedIndexedAccess tùy team). Nếu dự án cũ thì nâng dần bằng “ratchet”: fix mới trước, phần legacy làm từ từ.

  2. Ưu tiên type inference thay vì annotate mọi thứ (đỡ verbose, ít sai): chỉ annotate ở boundary (API, public function, component props, shared lib).

  3. Không lạm dụng any. Nếu bất đắc dĩ: dùng unknown + parse/validate.

  4. Tách layer type rõ ràng:

    • API DTO types (đúng như backend trả về)

    • Domain types (đúng cho business)

    • ViewModel/UI types (phục vụ render)

  5. Discriminated unions cho state (loading/success/error) thay vì boolean chồng chéo.

  6. Không “export type linh tinh”: chỉ export public contract; internal type để local để tránh phụ thuộc chéo.

  7. Naming convention: FooDto, Foo, FooVM hoặc FooApi, FooDomain, FooView.

  8. Codegen/validator cho API để tránh mismatch runtime.

Một câu chốt “Senior”: “TS là để giảm bug ở boundary và giúp refactor nhanh; mình tránh biến TS thành bài toán logic khó đọc cho team.”


2) “Xử lý type cho API response và shared types như thế nào?”

Mình hay trình bày theo 2 hướng (tùy mức độ trưởng thành của hệ thống):

A) Hướng “chuẩn bài” (khuyến nghị cho team lớn)

  • Single source of truth từ API spec:

    • Nếu có OpenAPI/Swagger: dùng openapi-typescript hoặc tool codegen tạo type + (option) client.

    • Nếu GraphQL: dùng graphql codegen.

  • Runtime validation:

    • Dùng Zod (hoặc io-ts) để parse/validate response → tránh “type đúng nhưng data sai”.

    • Pattern: schema.parse(data) rồi mới map sang domain.

  • Mapping DTO → Domain:

    • UserDto có thể có null/field thừa/field naming khác, nhưng User trong domain phải sạch và ổn định.

    • Mapping function là nơi xử lý: rename, default, normalize date, enum mapping…

Ví dụ cách nói:

  • “Em không dùng trực tiếp type DTO để render UI. Em parse/validate và map sang domain model, rồi UI chỉ phụ thuộc domain.”

B) Hướng “thực dụng” (khi chưa có spec/codegen)

  • Dùng unknown ở tầng fetcher, sau đó:

    • Viết type guard / zod schema cho endpoint quan trọng (auth, payment, core flows).

    • Endpoint phụ ít rủi ro có thể dùng typing nhẹ hơn nhưng vẫn tránh any.

Shared types (monorepo / multi-app)

  • Đặt packages/shared-types (hoặc @org/contracts) gồm:

    • domain types ổn định (không phụ thuộc React/Vue)

    • enums/constants

    • API contracts (nếu dùng chung)

  • Quy tắc versioning:

    • breaking change phải bump major

    • deprecate trước khi remove

  • Tránh circular deps: shared-types không import ngược từ app.


3) “Khi TypeScript gây phức tạp cho team junior, anh/chị giải quyết ra sao?”

Câu này họ muốn nghe “leadership + trade-off”, không chỉ kỹ thuật.

Cách mình xử lý (rất thực tế):

  1. Đặt nguyên tắc: TS phục vụ readability trước

    • Cấm “type puzzle” nếu không cần thiết.

    • Ưu tiên type đơn giản, rõ ràng; generic chỉ khi đem lại lợi ích thật (reusability/safer boundary).

  2. Tạo “happy path” cho junior

    • Chuẩn hoá pattern: useQuery wrapper typed sẵn, apiClient typed sẵn, Result<T> / AsyncState<T> typed sẵn.

    • Junior chỉ cần “đi theo rail”, ít phải tự nghĩ generic.

  3. Code review theo hướng coaching

    • Nếu thấy PR bị TS error: hướng dẫn cách đọc error, cách narrow unknown, cách fix đúng.

    • Gợi ý “đổi thiết kế” thay vì “ép type”.

  4. Giảm strictness theo lộ trình nếu team còn yếu

    • Không tắt strict toàn dự án; dùng // @ts-expect-error có lý do + ticket, hoặc isolate legacy folder.

  5. Docs ngắn + examples

    • 1 trang “TS playbook” nội bộ: common patterns, naming, do/don’t, vài snippet mẫu.

  6. Đo hiệu quả

    • Theo dõi: số bug từ mismatch API, thời gian refactor, tốc độ onboard junior. Nếu TS đang làm chậm quá → đơn giản hóa pattern.

Một câu kết hay: “Mục tiêu là team ship nhanh và an toàn. Nếu TS đang làm junior ‘sợ’, thì mình chuẩn hóa abstraction, giảm độ ma thuật, và nâng dần tiêu chuẩn theo thời gian.”


Nếu bạn muốn, mình có thể viết luôn một câu trả lời hoàn chỉnh kiểu interview (1–2 phút nói) cho cả 3 câu theo đúng phong cách Senior/Principal, hoặc mock theo bối cảnh bạn đang apply (React/Next vs Vue/Nuxt).

trả lời lại 3 câu trên dễ hiểu hơn

OK, mình trả lời lại 3 câu theo cách đơn giản – dễ hiểu – đúng kiểu nói khi phỏng vấn, phù hợp cả với junior lẫn interviewer 👍


1) Anh/chị sử dụng TypeScript ở mức nào? Best practice?

Mình sử dụng TypeScript thường xuyên trong hầu hết dự án frontend, đặc biệt là React/Next hoặc Vue/Nuxt.

Cách mình dùng khá thực tế:

  • TypeScript giúp bắt lỗi sớm, dễ refactorcode rõ ràng hơn, chứ không phải để làm code phức tạp.

  • Mình dùng tốt các tính năng phổ biến như:

    • interface / type

    • generic cơ bản

    • union type (A | B)

    • utility types như Pick, Omit, Partial

Best practice mình hay áp dụng:

  • Chỉ viết type rõ ràng ở những chỗ quan trọng:
    API, props component, function public

  • Không lạm dụng any; nếu chưa rõ data thì dùng unknown

  • Không ép type quá chặt làm code khó đọc

  • Đặt tên type rõ ràng, dễ hiểu cho cả team

👉 Nói ngắn gọn: TypeScript để code an toàn và dễ maintain, không phải để “show kỹ thuật”.


2) Anh/chị xử lý type cho API response và shared types như thế nào?

Với API response, mình không dùng trực tiếp data từ API cho UI.

Cách mình thường làm:

  • API trả về → có type riêng (ví dụ UserApi)

  • Sau đó map sang type dùng trong app (ví dụ User)

  • UI chỉ làm việc với type đã “sạch” và ổn định

Ví dụ cách nghĩ:

  • API có thể trả null, thiếu field, hoặc format chưa đẹp

  • Mình xử lý ở 1 chỗ → UI không phải lo

Với shared types:

  • Nếu nhiều project dùng chung, mình tách ra thành folder hoặc package riêng

  • Chỉ để những type ổn định (domain, enum, constant)

  • Tránh để type UI hoặc framework-specific vào shared

👉 Mục tiêu là tránh bug do API thay đổidễ maintain khi app lớn lên.


3) Khi TypeScript gây phức tạp cho team junior, anh/chị giải quyết ra sao?

Mình ưu tiên team hiểu và làm được, hơn là dùng TypeScript quá nâng cao.

Cách mình xử lý:

  • Không bắt junior viết type phức tạp

  • Chuẩn hóa sẵn:

    • API client

    • common hooks

    • common types

  • Junior chỉ cần dùng lại, không phải tự nghĩ nhiều về generic

Trong code review:

  • Mình giải thích lỗi TS theo cách dễ hiểu

  • Nếu type đang làm code khó đọc → mình đơn giản hóa

Nếu team còn yếu:

  • Có thể giảm độ strict ở một số chỗ

  • Làm từng bước, không ép toàn bộ ngay từ đầu

👉 Quan điểm của mình là:
TypeScript phải giúp team code tốt hơn, không làm team sợ code.


1) Anh/chị đã từng đóng vai trò Technical Lead chưa? Phạm vi trách nhiệm?

Mình đã từng đảm nhiệm vai trò Technical Lead trong một số dự án.

Phạm vi trách nhiệm của mình thường gồm:

  • Định hướng kiến trúc frontend (structure, state management, coding convention)

  • Review và đảm bảo chất lượng code

  • Hỗ trợ member khi gặp vấn đề kỹ thuật

  • Phối hợp với PM, designer, backend để đảm bảo solution khả thi

  • Chia nhỏ task và estimate cùng team

Ngoài kỹ thuật, mình cũng:

  • Giúp junior hiểu cách làm, không chỉ “làm theo”

  • Đảm bảo tiến độ nhưng vẫn giữ chất lượng

👉 Vai trò của mình là giúp team code tốt và ship ổn định.


2) Anh/chị review code của member theo những tiêu chí nào?

Khi review code, mình tập trung vào những điểm chính sau:

  1. Correctness

    • Logic đúng không?

    • Có xử lý edge case chưa?

  2. Readability

    • Code có dễ đọc, dễ hiểu cho người khác không?

    • Naming rõ ràng chưa?

  3. Maintainability

    • Sau này sửa có dễ không?

    • Có chia component / function hợp lý không?

  4. Performance & UX cơ bản

    • Có re-render dư thừa không?

    • Loading / error state đã xử lý chưa?

  5. Consistency

    • Có đúng convention của team không?

Với junior:

  • Mình ưu tiên góp ý mang tính hướng dẫn

  • Không bắt tối ưu quá sớm

👉 Review không phải để bắt lỗi, mà để nâng chất lượng chung của team.


3) Khi có tranh luận về kỹ thuật trong team, anh/chị giải quyết ra sao?

Khi có tranh luận, mình cố gắng không quyết định theo cảm tính hay vai vế.

Cách mình xử lý:

  • Lắng nghe các ý kiến và lý do đằng sau

  • So sánh dựa trên:

    • business impact

    • độ phức tạp

    • khả năng maintain

  • Nếu cần, mình đề xuất:

    • làm proof of concept nhỏ

    • chọn giải pháp đơn giản hơn cho phase đầu

Nếu vẫn chưa thống nhất:

  • Mình đưa ra quyết định với tư cách tech lead

  • Nhưng luôn giải thích rõ lý do để team hiểu

👉 Mục tiêu cuối cùng là quyết định tốt cho sản phẩm và giữ tinh thần team.


1) Giải thích CORS / Event Bubbling / Rendering process của browser

🔹 CORS là gì? (cách giải thích ngắn, dễ hiểu)

CORS là cơ chế bảo mật của browser, nhằm kiểm soát việc frontend gọi API từ domain khác.

  • Nếu frontend gọi API khác origin (khác domain / port / protocol)

  • Browser sẽ kiểm tra response header từ server

  • Nếu server không cho phép → browser chặn request (dù server có thể đã xử lý xong)

Ví dụ:

  • Frontend ở app.example.com

  • API ở api.example.com
    → Cần cấu hình CORS ở backend

👉 Quan trọng: CORS là vấn đề của browser, không phải của backend logic.


🔹 Event Bubbling là gì?

Event bubbling là cơ chế mà event được lan từ element con lên element cha.

Ví dụ:

  • Click vào button bên trong div

  • Event chạy ở button → div → body → document

Ứng dụng thực tế:

  • Dùng event delegation để bắt event cho nhiều element

  • Có thể dùng event.stopPropagation() để chặn bubbling khi cần

👉 Hiểu bubbling giúp xử lý đúng các bug liên quan đến click, modal, dropdown.


🔹 Rendering process của browser (giải thích đơn giản)

Quy trình render cơ bản của browser:

  1. Parse HTML → tạo DOM

  2. Parse CSS → tạo CSSOM

  3. DOM + CSSOM → Render Tree

  4. Layout (tính toán vị trí, kích thước)

  5. Paint (vẽ pixel lên màn hình)

👉 Nếu thay đổi layout nhiều lần hoặc CSS nặng → ảnh hưởng performance.


2) Các khác biệt browser anh/chị từng gặp trong thực tế?

Một số khác biệt mình từng gặp:

  • CSS khác nhau giữa Chrome / Safari

    • Flexbox, position: sticky, gap trong flex

  • Safari có nhiều bug hơn

    • Date parsing (new Date('2024-01-01'))

    • Scroll behavior, focus input

  • Event handling

    • Touch event khác desktop

    • passive event listener trên mobile

  • Performance

    • Safari render animation kém hơn Chrome

  • Input / Form

    • Style input, select khác nhau giữa browser

Cách mình xử lý:

  • Test sớm trên Chrome, Safari, Firefox

  • Dùng normalize / reset CSS

  • Tránh dùng feature mới nếu chưa stable

  • Có fallback hoặc polyfill khi cần

👉 Quan điểm của mình là:
Không assume “chạy trên Chrome là đủ”, đặc biệt với sản phẩm cho end-user.


1) Những vấn đề web security frontend cần chú ý là gì?

Những vấn đề mình luôn chú ý ở frontend gồm:

🔹 XSS (Cross-Site Scripting)

  • Xảy ra khi app render nội dung không được sanitize

  • Ví dụ: render HTML từ user input

Cách mình phòng tránh:

  • Không dùng dangerouslySetInnerHTML nếu không cần

  • Escape input/output

  • Dùng library sanitize khi bắt buộc render HTML

  • Kết hợp CSP từ phía server


🔹 CSRF (Cross-Site Request Forgery)

  • Xảy ra khi browser tự động gửi cookie sang site khác

Frontend cần làm:

  • Dùng CSRF token cho request quan trọng

  • Với API auth bằng cookie: luôn set SameSite

  • Phối hợp backend để kiểm soát origin


🔹 Token & Data exposure

  • Không lưu token nhạy cảm bừa bãi trong localStorage

  • Không log thông tin nhạy cảm lên console

  • Tránh hard-code secret trong frontend


🔹 Clickjacking

  • Trang bị embed vào iframe độc hại

Cách xử lý:

  • Kết hợp backend set X-Frame-Options hoặc CSP

  • Frontend kiểm tra context nếu cần


🔹 Third-party risk

  • Script bên thứ ba có thể inject code

  • Cẩn trọng khi dùng tracking / analytics

👉 Với mình, frontend security là kết hợp giữa code, browser behavior và phối hợp backend.


2) Anh/chị đã từng xử lý authentication / authorization ở frontend chưa?

Có, mình đã xử lý authentication và authorization ở frontend trong nhiều dự án.

🔹 Authentication (đăng nhập)

Frontend thường chịu trách nhiệm:

  • Login / logout flow

  • Lưu trạng thái đăng nhập

  • Refresh session / token (theo design của backend)

  • Redirect khi chưa login

Mình đã làm với:

  • Token-based auth (JWT)

  • Cookie-based session

  • OAuth (Google, SSO…)


🔹 Authorization (phân quyền)

Frontend xử lý ở nhiều mức:

  • Route guard (chặn truy cập page)

  • UI-level permission (ẩn/hiện button, action)

  • Feature flag theo role

Cách mình làm:

  • Nhận role / permission từ backend

  • Tạo layer check permission chung

  • Không hard-code logic phân quyền rải rác

👉 Lưu ý mình luôn nhấn mạnh khi phỏng vấn:
Frontend chỉ hỗ trợ authorization về UX, backend vẫn là nơi quyết định cuối cùng.


🔚 Câu chốt kiểu Senior

Frontend security không phải để “chặn hacker”, mà để giảm rủi ro, bảo vệ user và không tạo lỗ hổng cho hệ thống.


1) Những vấn đề web security frontend cần chú ý là gì?

Những vấn đề mình luôn chú ý ở frontend gồm:

🔹 XSS (Cross-Site Scripting)

  • Xảy ra khi app render nội dung không được sanitize

  • Ví dụ: render HTML từ user input

Cách mình phòng tránh:

  • Không dùng dangerouslySetInnerHTML nếu không cần

  • Escape input/output

  • Dùng library sanitize khi bắt buộc render HTML

  • Kết hợp CSP từ phía server


🔹 CSRF (Cross-Site Request Forgery)

  • Xảy ra khi browser tự động gửi cookie sang site khác

Frontend cần làm:

  • Dùng CSRF token cho request quan trọng

  • Với API auth bằng cookie: luôn set SameSite

  • Phối hợp backend để kiểm soát origin


🔹 Token & Data exposure

  • Không lưu token nhạy cảm bừa bãi trong localStorage

  • Không log thông tin nhạy cảm lên console

  • Tránh hard-code secret trong frontend


🔹 Clickjacking

  • Trang bị embed vào iframe độc hại

Cách xử lý:

  • Kết hợp backend set X-Frame-Options hoặc CSP

  • Frontend kiểm tra context nếu cần


🔹 Third-party risk

  • Script bên thứ ba có thể inject code

  • Cẩn trọng khi dùng tracking / analytics

👉 Với mình, frontend security là kết hợp giữa code, browser behavior và phối hợp backend.


2) Anh/chị đã từng xử lý authentication / authorization ở frontend chưa?

Có, mình đã xử lý authentication và authorization ở frontend trong nhiều dự án.

🔹 Authentication (đăng nhập)

Frontend thường chịu trách nhiệm:

  • Login / logout flow

  • Lưu trạng thái đăng nhập

  • Refresh session / token (theo design của backend)

  • Redirect khi chưa login

Mình đã làm với:

  • Token-based auth (JWT)

  • Cookie-based session

  • OAuth (Google, SSO…)


🔹 Authorization (phân quyền)

Frontend xử lý ở nhiều mức:

  • Route guard (chặn truy cập page)

  • UI-level permission (ẩn/hiện button, action)

  • Feature flag theo role

Cách mình làm:

  • Nhận role / permission từ backend

  • Tạo layer check permission chung

  • Không hard-code logic phân quyền rải rác

👉 Lưu ý mình luôn nhấn mạnh khi phỏng vấn:
Frontend chỉ hỗ trợ authorization về UX, backend vẫn là nơi quyết định cuối cùng.


🔚 Câu chốt kiểu Senior

Frontend security không phải để “chặn hacker”, mà để giảm rủi ro, bảo vệ user và không tạo lỗ hổng cho hệ thống. 

Comment