- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
746 lines
22 KiB
Markdown
746 lines
22 KiB
Markdown
# Security by Design
|
|
|
|
## Навигация
|
|
- [🏠 Главная страница курса](../../../README.md)
|
|
- [📚 Модуль 6](../README.md)
|
|
|
|
---
|
|
|
|
## Принципы Security by Design
|
|
|
|
### 1. Secure by Default
|
|
- Безопасные настройки по умолчанию
|
|
- Минимальные права доступа
|
|
- Защита от случайных ошибок
|
|
|
|
### 2. Fail Secure
|
|
- При отказе система переходит в безопасное состояние
|
|
- Блокировка доступа при ошибках
|
|
- Логирование всех событий безопасности
|
|
|
|
### 3. Security as Code
|
|
- Безопасность как часть кода
|
|
- Автоматизированные проверки безопасности
|
|
- Версионирование политик безопасности
|
|
|
|
## Моделирование угроз
|
|
|
|
### STRIDE Model
|
|
- **S**poofing (Подмена)
|
|
- **T**ampering (Изменение)
|
|
- **R**epudiation (Отказ)
|
|
- **I**nformation Disclosure (Раскрытие информации)
|
|
- **D**enial of Service (Отказ в обслуживании)
|
|
- **E**levation of Privilege (Повышение привилегий)
|
|
|
|
### Пример Threat Model:
|
|
```yaml
|
|
# threat-model.yml
|
|
application: "E-commerce Platform"
|
|
components:
|
|
- name: "User Authentication"
|
|
threats:
|
|
- type: "Spoofing"
|
|
description: "User impersonation"
|
|
mitigations:
|
|
- "Strong password policy"
|
|
- "Multi-factor authentication"
|
|
|
|
- name: "Payment Processing"
|
|
threats:
|
|
- type: "Tampering"
|
|
description: "Payment data modification"
|
|
mitigations:
|
|
- "Data encryption"
|
|
- "Digital signatures"
|
|
```
|
|
|
|
## Архитектура безопасности
|
|
|
|
### 1. Zero Trust Architecture
|
|
**Принцип:** "Никогда не доверяй, всегда проверяй"
|
|
|
|
```java
|
|
@Component
|
|
public class ZeroTrustFilter implements Filter {
|
|
@Override
|
|
public void doFilter(ServletRequest request, ServletResponse response,
|
|
FilterChain chain) throws IOException, ServletException {
|
|
|
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
|
|
|
// проверяем каждую аутентификацию
|
|
if (!isAuthenticated(httpRequest)) {
|
|
throw new AuthenticationException("Authentication required");
|
|
}
|
|
|
|
// проверяем каждую авторизацию
|
|
if (!isAuthorized(httpRequest)) {
|
|
throw new AuthorizationException("Access denied");
|
|
}
|
|
|
|
// проверяем устройство
|
|
if (!isDeviceTrusted(httpRequest)) {
|
|
throw new SecurityException("Untrusted device");
|
|
}
|
|
|
|
chain.doFilter(request, response);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Microsegmentation
|
|
**Принцип:** Разделение сети на мелкие сегменты
|
|
|
|
```yaml
|
|
# network-policy.yml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: order-service-policy
|
|
spec:
|
|
podSelector:
|
|
matchLabels:
|
|
app: order-service
|
|
policyTypes:
|
|
- Ingress
|
|
- Egress
|
|
ingress:
|
|
- from:
|
|
- podSelector:
|
|
matchLabels:
|
|
app: api-gateway
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
egress:
|
|
- to:
|
|
- podSelector:
|
|
matchLabels:
|
|
app: payment-service
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
```
|
|
|
|
## Аутентификация и авторизация
|
|
|
|
### Аутентификация
|
|
|
|
#### 1. Password-based Authentication
|
|
```java
|
|
@Service
|
|
public class AuthenticationService {
|
|
@Autowired
|
|
private PasswordEncoder passwordEncoder;
|
|
|
|
@Autowired
|
|
private UserRepository userRepository;
|
|
|
|
public AuthenticationResult authenticate(String username, String password) {
|
|
User user = userRepository.findByUsername(username);
|
|
|
|
if (user == null) {
|
|
return AuthenticationResult.failure("User not found");
|
|
}
|
|
|
|
if (!passwordEncoder.matches(password, user.getPasswordHash())) {
|
|
return AuthenticationResult.failure("Invalid password");
|
|
}
|
|
|
|
if (!user.isActive()) {
|
|
return AuthenticationResult.failure("User account is disabled");
|
|
}
|
|
|
|
return AuthenticationResult.success(user);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Multi-Factor Authentication (MFA)
|
|
```java
|
|
@Service
|
|
public class MFAService {
|
|
@Autowired
|
|
private TOTPGenerator totpGenerator;
|
|
|
|
@Autowired
|
|
private SMSService smsService;
|
|
|
|
public void enableMFA(Long userId, String phoneNumber) {
|
|
String secret = totpGenerator.generateSecret();
|
|
userRepository.updateMFASecret(userId, secret);
|
|
userRepository.updatePhoneNumber(userId, phoneNumber);
|
|
}
|
|
|
|
public boolean verifyMFA(Long userId, String code) {
|
|
User user = userRepository.findById(userId);
|
|
String secret = user.getMFASecret();
|
|
|
|
return totpGenerator.verifyCode(secret, code);
|
|
}
|
|
|
|
public void sendSMS(Long userId, String code) {
|
|
User user = userRepository.findById(userId);
|
|
smsService.sendSMS(user.getPhoneNumber(), "Your verification code: " + code);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. OAuth 2.0 / OpenID Connect
|
|
```java
|
|
@Configuration
|
|
@EnableWebSecurity
|
|
public class SecurityConfig {
|
|
@Bean
|
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
|
http
|
|
.oauth2Login(oauth2 -> oauth2
|
|
.userInfoEndpoint(userInfo -> userInfo
|
|
.userService(customOAuth2UserService)
|
|
)
|
|
)
|
|
.authorizeHttpRequests(authz -> authz
|
|
.requestMatchers("/public/**").permitAll()
|
|
.requestMatchers("/admin/**").hasRole("ADMIN")
|
|
.anyRequest().authenticated()
|
|
);
|
|
|
|
return http.build();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Авторизация
|
|
|
|
#### 1. Role-Based Access Control (RBAC)
|
|
```java
|
|
@Entity
|
|
public class User {
|
|
@Id
|
|
private Long id;
|
|
|
|
@ManyToMany(fetch = FetchType.EAGER)
|
|
@JoinTable(
|
|
name = "user_roles",
|
|
joinColumns = @JoinColumn(name = "user_id"),
|
|
inverseJoinColumns = @JoinColumn(name = "role_id")
|
|
)
|
|
private Set<Role> roles = new HashSet<>();
|
|
}
|
|
|
|
@Entity
|
|
public class Role {
|
|
@Id
|
|
private Long id;
|
|
|
|
private String name;
|
|
|
|
@ManyToMany(fetch = FetchType.EAGER)
|
|
@JoinTable(
|
|
name = "role_permissions",
|
|
joinColumns = @JoinColumn(name = "role_id"),
|
|
inverseJoinColumns = @JoinColumn(name = "permission_id")
|
|
)
|
|
private Set<Permission> permissions = new HashSet<>();
|
|
}
|
|
```
|
|
|
|
#### 2. Attribute-Based Access Control (ABAC)
|
|
```java
|
|
@Component
|
|
public class ABACPolicyEngine {
|
|
public boolean evaluate(Policy policy, AccessRequest request) {
|
|
// проверяем субъект
|
|
if (!policy.getSubject().matches(request.getSubject())) {
|
|
return false;
|
|
}
|
|
|
|
// проверяем ресурс
|
|
if (!policy.getResource().matches(request.getResource())) {
|
|
return false;
|
|
}
|
|
|
|
// проверяем действие
|
|
if (!policy.getAction().matches(request.getAction())) {
|
|
return false;
|
|
}
|
|
|
|
// проверяем контекст
|
|
if (!policy.getContext().matches(request.getContext())) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Пример политики
|
|
Policy policy = Policy.builder()
|
|
.subject("role:manager")
|
|
.resource("department:finance")
|
|
.action("read")
|
|
.context("time:business_hours")
|
|
.build();
|
|
```
|
|
|
|
#### 3. JWT Tokens
|
|
```java
|
|
@Service
|
|
public class JWTService {
|
|
private final String secretKey = "mySecretKey";
|
|
private final int jwtExpiration = 86400000; // 24 hours
|
|
|
|
public String generateToken(UserDetails userDetails) {
|
|
Map<String, Object> claims = new HashMap<>();
|
|
claims.put("roles", userDetails.getAuthorities());
|
|
claims.put("userId", userDetails.getUsername());
|
|
|
|
return createToken(claims, userDetails.getUsername());
|
|
}
|
|
|
|
private String createToken(Map<String, Object> claims, String subject) {
|
|
return Jwts.builder()
|
|
.setClaims(claims)
|
|
.setSubject(subject)
|
|
.setIssuedAt(new Date(System.currentTimeMillis()))
|
|
.setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
|
|
.signWith(SignatureAlgorithm.HS512, secretKey)
|
|
.compact();
|
|
}
|
|
|
|
public Boolean validateToken(String token, UserDetails userDetails) {
|
|
final String username = extractUsername(token);
|
|
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
|
}
|
|
}
|
|
```
|
|
|
|
## Безопасность API
|
|
|
|
### Лучшие практики безопасности API
|
|
|
|
#### 1. Input Validation
|
|
```java
|
|
@RestController
|
|
@Validated
|
|
public class UserController {
|
|
@PostMapping("/users")
|
|
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
|
|
// валидация выполняется автоматически через @Valid
|
|
User user = userService.createUser(request);
|
|
return ResponseEntity.ok(user);
|
|
}
|
|
}
|
|
|
|
public class CreateUserRequest {
|
|
@NotBlank(message = "Username is required")
|
|
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
|
|
private String username;
|
|
|
|
@NotBlank(message = "Email is required")
|
|
@Email(message = "Email must be valid")
|
|
private String email;
|
|
|
|
@NotBlank(message = "Password is required")
|
|
@Size(min = 8, message = "Password must be at least 8 characters")
|
|
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$",
|
|
message = "Password must contain at least one uppercase letter, one lowercase letter, one number and one special character")
|
|
private String password;
|
|
}
|
|
```
|
|
|
|
#### 2. Rate Limiting
|
|
```java
|
|
@Component
|
|
public class RateLimitingFilter implements Filter {
|
|
private final Map<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();
|
|
|
|
@Override
|
|
public void doFilter(ServletRequest request, ServletResponse response,
|
|
FilterChain chain) throws IOException, ServletException {
|
|
|
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
|
String clientId = getClientId(httpRequest);
|
|
|
|
RateLimiter rateLimiter = rateLimiters.computeIfAbsent(clientId,
|
|
k -> RateLimiter.create(10.0)); // 10 запросов в секунду
|
|
|
|
if (!rateLimiter.tryAcquire()) {
|
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
|
httpResponse.setStatus(429); // Too Many Requests
|
|
httpResponse.getWriter().write("Rate limit exceeded");
|
|
return;
|
|
}
|
|
|
|
chain.doFilter(request, response);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. API Versioning
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api/v1/users")
|
|
public class UserControllerV1 {
|
|
@GetMapping("/{id}")
|
|
public UserV1 getUser(@PathVariable Long id) {
|
|
return userService.getUserV1(id);
|
|
}
|
|
}
|
|
|
|
@RestController
|
|
@RequestMapping("/api/v2/users")
|
|
public class UserControllerV2 {
|
|
@GetMapping("/{id}")
|
|
public UserV2 getUser(@PathVariable Long id) {
|
|
return userService.getUserV2(id);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Безопасность API Gateway
|
|
|
|
```yaml
|
|
# api-gateway-security.yml
|
|
apiVersion: networking.istio.io/v1alpha3
|
|
kind: AuthorizationPolicy
|
|
metadata:
|
|
name: api-gateway-policy
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: api-gateway
|
|
rules:
|
|
- from:
|
|
- source:
|
|
principals: ["cluster.local/ns/default/sa/api-gateway"]
|
|
to:
|
|
- operation:
|
|
methods: ["GET", "POST"]
|
|
paths: ["/api/v1/*"]
|
|
- from:
|
|
- source:
|
|
principals: ["cluster.local/ns/default/sa/admin-service"]
|
|
to:
|
|
- operation:
|
|
methods: ["*"]
|
|
paths: ["/admin/*"]
|
|
```
|
|
|
|
## Безопасность данных
|
|
|
|
### Классификация данных
|
|
|
|
#### 1. Data Sensitivity Levels
|
|
- **Public** — общедоступные данные
|
|
- **Internal** — внутренние данные
|
|
- **Confidential** — конфиденциальные данные
|
|
- **Restricted** — ограниченные данные
|
|
|
|
```java
|
|
@Entity
|
|
public class User {
|
|
@Id
|
|
private Long id;
|
|
|
|
@Column(name = "username")
|
|
@DataClassification(level = DataClassification.Level.INTERNAL)
|
|
private String username;
|
|
|
|
@Column(name = "email")
|
|
@DataClassification(level = DataClassification.Level.CONFIDENTIAL)
|
|
private String email;
|
|
|
|
@Column(name = "ssn")
|
|
@DataClassification(level = DataClassification.Level.RESTRICTED)
|
|
@Encrypted
|
|
private String ssn;
|
|
}
|
|
```
|
|
|
|
#### 2. Data Masking
|
|
```java
|
|
@Service
|
|
public class DataMaskingService {
|
|
public User maskUserData(User user, UserRole requesterRole) {
|
|
User maskedUser = new User();
|
|
maskedUser.setId(user.getId());
|
|
|
|
switch (requesterRole) {
|
|
case ADMIN:
|
|
// админы видят все данные
|
|
maskedUser.setEmail(user.getEmail());
|
|
maskedUser.setSsn(user.getSsn());
|
|
break;
|
|
case MANAGER:
|
|
// менеджеры видят частично замаскированные данные
|
|
maskedUser.setEmail(maskEmail(user.getEmail()));
|
|
maskedUser.setSsn(maskSSN(user.getSsn()));
|
|
break;
|
|
case USER:
|
|
// обычные пользователи видят только базовую информацию
|
|
maskedUser.setEmail(maskEmail(user.getEmail()));
|
|
maskedUser.setSsn("***-**-****");
|
|
break;
|
|
}
|
|
|
|
return maskedUser;
|
|
}
|
|
|
|
private String maskEmail(String email) {
|
|
String[] parts = email.split("@");
|
|
String username = parts[0];
|
|
String domain = parts[1];
|
|
|
|
if (username.length() <= 2) {
|
|
return "*@" + domain;
|
|
}
|
|
|
|
return username.substring(0, 2) + "*".repeat(username.length() - 2) + "@" + domain;
|
|
}
|
|
|
|
private String maskSSN(String ssn) {
|
|
return "***-**-" + ssn.substring(ssn.length() - 4);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Шифрование данных
|
|
|
|
#### 1. Encryption at Rest
|
|
```java
|
|
@Entity
|
|
public class PaymentCard {
|
|
@Id
|
|
private Long id;
|
|
|
|
@Column(name = "card_number")
|
|
@Convert(converter = EncryptedStringConverter.class)
|
|
private String cardNumber;
|
|
|
|
@Column(name = "cvv")
|
|
@Convert(converter = EncryptedStringConverter.class)
|
|
private String cvv;
|
|
}
|
|
|
|
@Converter
|
|
public class EncryptedStringConverter implements AttributeConverter<String, String> {
|
|
@Autowired
|
|
private EncryptionService encryptionService;
|
|
|
|
@Override
|
|
public String convertToDatabaseColumn(String attribute) {
|
|
return encryptionService.encrypt(attribute);
|
|
}
|
|
|
|
@Override
|
|
public String convertToEntityAttribute(String dbData) {
|
|
return encryptionService.decrypt(dbData);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Encryption in Transit
|
|
```java
|
|
@Configuration
|
|
public class SSLConfig {
|
|
@Bean
|
|
public RestTemplate restTemplate() throws Exception {
|
|
SSLContext sslContext = SSLContextBuilder.create()
|
|
.loadTrustMaterial(null, (certificate, authType) -> true)
|
|
.build();
|
|
|
|
HttpClient httpClient = HttpClients.custom()
|
|
.setSSLContext(sslContext)
|
|
.build();
|
|
|
|
HttpComponentsClientHttpRequestFactory factory =
|
|
new HttpComponentsClientHttpRequestFactory(httpClient);
|
|
|
|
return new RestTemplate(factory);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Соответствие требованиям
|
|
|
|
### GDPR (Общий регламент по защите данных)
|
|
|
|
#### 1. Data Subject Rights
|
|
```java
|
|
@Service
|
|
public class GDPRService {
|
|
public void handleDataSubjectRequest(DataSubjectRequest request) {
|
|
switch (request.getType()) {
|
|
case ACCESS:
|
|
provideDataAccess(request.getSubjectId());
|
|
break;
|
|
case RECTIFICATION:
|
|
rectifyData(request.getSubjectId(), request.getData());
|
|
break;
|
|
case ERASURE:
|
|
eraseData(request.getSubjectId());
|
|
break;
|
|
case PORTABILITY:
|
|
provideDataPortability(request.getSubjectId());
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void eraseData(Long subjectId) {
|
|
// удаляем персональные данные
|
|
userRepository.deletePersonalData(subjectId);
|
|
|
|
// логируем удаление
|
|
auditService.logDataErasure(subjectId);
|
|
|
|
// уведомляем заинтересованные системы
|
|
notificationService.notifyDataErasure(subjectId);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Consent Management
|
|
```java
|
|
@Entity
|
|
public class Consent {
|
|
@Id
|
|
private Long id;
|
|
|
|
private Long userId;
|
|
private String purpose;
|
|
private ConsentStatus status;
|
|
private LocalDateTime givenAt;
|
|
private LocalDateTime withdrawnAt;
|
|
|
|
public boolean isValid() {
|
|
return status == ConsentStatus.GIVEN && withdrawnAt == null;
|
|
}
|
|
}
|
|
|
|
@Service
|
|
public class ConsentService {
|
|
public void giveConsent(Long userId, String purpose) {
|
|
Consent consent = new Consent();
|
|
consent.setUserId(userId);
|
|
consent.setPurpose(purpose);
|
|
consent.setStatus(ConsentStatus.GIVEN);
|
|
consent.setGivenAt(LocalDateTime.now());
|
|
|
|
consentRepository.save(consent);
|
|
}
|
|
|
|
public void withdrawConsent(Long userId, String purpose) {
|
|
Consent consent = consentRepository.findByUserIdAndPurpose(userId, purpose);
|
|
if (consent != null) {
|
|
consent.setStatus(ConsentStatus.WITHDRAWN);
|
|
consent.setWithdrawnAt(LocalDateTime.now());
|
|
consentRepository.save(consent);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### PCI DSS (Стандарт безопасности данных индустрии платежных карт)
|
|
|
|
#### 1. Card Data Protection
|
|
```java
|
|
@Service
|
|
public class PCIService {
|
|
public String tokenizeCard(String cardNumber) {
|
|
// генерируем токен вместо хранения номера карты
|
|
String token = UUID.randomUUID().toString();
|
|
|
|
// сохраняем токен в безопасном хранилище
|
|
secureStorage.storeToken(token, cardNumber);
|
|
|
|
return token;
|
|
}
|
|
|
|
public String detokenizeCard(String token) {
|
|
// получаем номер карты по токену
|
|
return secureStorage.getCardByToken(token);
|
|
}
|
|
|
|
public boolean validateCard(String cardNumber) {
|
|
// проверяем номер карты по алгоритму Луна
|
|
return luhnAlgorithm.validate(cardNumber);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Secure Payment Processing
|
|
```java
|
|
@Service
|
|
public class PaymentService {
|
|
@Transactional
|
|
public PaymentResult processPayment(PaymentRequest request) {
|
|
// валидируем данные карты
|
|
if (!validateCardData(request.getCardData())) {
|
|
return PaymentResult.failure("Invalid card data");
|
|
}
|
|
|
|
// токенизируем данные карты
|
|
String token = tokenizeCard(request.getCardData().getNumber());
|
|
|
|
// обрабатываем платеж
|
|
PaymentResult result = paymentProcessor.processPayment(request);
|
|
|
|
// логируем транзакцию
|
|
auditService.logPaymentTransaction(request, result);
|
|
|
|
return result;
|
|
}
|
|
}
|
|
```
|
|
|
|
### SOX (Закон Сарбейнса-Оксли)
|
|
|
|
#### 1. Financial Data Controls
|
|
```java
|
|
@Service
|
|
public class FinancialControlService {
|
|
public void validateFinancialTransaction(FinancialTransaction transaction) {
|
|
// проверяем авторизацию
|
|
if (!isAuthorized(transaction.getAmount())) {
|
|
throw new AuthorizationException("Transaction amount exceeds authorization limit");
|
|
}
|
|
|
|
// проверяем дублирование
|
|
if (isDuplicateTransaction(transaction)) {
|
|
throw new DuplicateTransactionException("Duplicate transaction detected");
|
|
}
|
|
|
|
// проверяем целостность данных
|
|
if (!validateDataIntegrity(transaction)) {
|
|
throw new DataIntegrityException("Data integrity check failed");
|
|
}
|
|
}
|
|
|
|
public void auditFinancialData() {
|
|
// аудит финансовых данных
|
|
List<FinancialTransaction> transactions = getTransactionsForAudit();
|
|
|
|
for (FinancialTransaction transaction : transactions) {
|
|
validateTransaction(transaction);
|
|
logAuditTrail(transaction);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Заключение
|
|
|
|
Security by Design обеспечивает встроенную безопасность на всех уровнях приложения:
|
|
|
|
1. **Принципы безопасности** — Secure by Default, Fail Secure, Security as Code
|
|
2. **Моделирование угроз** — STRIDE модель для выявления рисков
|
|
3. **Архитектура безопасности** — Zero Trust, Microsegmentation
|
|
4. **Аутентификация и авторизация** — MFA, RBAC, ABAC, JWT
|
|
5. **Безопасность API** — Валидация, Rate Limiting, Versioning
|
|
6. **Безопасность данных** — Классификация, Маскирование, Шифрование
|
|
7. **Соответствие требованиям** — GDPR, PCI DSS, SOX
|
|
|
|
Интеграция этих принципов в процесс разработки обеспечивает надежную защиту приложения от угроз безопасности.
|