or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mddata-binding.mddata-components.mdindex.mdlayouts.mdrouting.mdsecurity.mdserver-communication.mdtheming.md

security.mddocs/

0

# Security

1

2

Vaadin provides comprehensive security features including authentication, authorization, CSRF protection, and integration with popular security frameworks like Spring Security. The platform includes both declarative and programmatic security approaches.

3

4

## Core Imports

5

6

```java

7

// Security annotations

8

import com.vaadin.flow.server.auth.AnonymousAllowed;

9

import com.vaadin.flow.server.auth.PermitAll;

10

import com.vaadin.flow.server.auth.DenyAll;

11

import com.vaadin.flow.server.auth.RolesAllowed;

12

13

// Login components

14

import com.vaadin.flow.component.login.LoginForm;

15

import com.vaadin.flow.component.login.LoginOverlay;

16

import com.vaadin.flow.component.login.AbstractLogin.LoginEvent;

17

import com.vaadin.flow.component.login.AbstractLogin.ForgotPasswordEvent;

18

import com.vaadin.flow.component.login.LoginI18n;

19

20

// Navigation guards and observers

21

import com.vaadin.flow.router.BeforeEnterObserver;

22

import com.vaadin.flow.router.BeforeEnterEvent;

23

import com.vaadin.flow.router.BeforeLeaveObserver;

24

import com.vaadin.flow.router.BeforeLeaveEvent;

25

26

// Session and security context

27

import com.vaadin.flow.server.VaadinSession;

28

import com.vaadin.flow.server.VaadinService;

29

import com.vaadin.flow.server.VaadinRequest;

30

import com.vaadin.flow.component.UI;

31

32

// Component events

33

import com.vaadin.flow.component.ComponentEventListener;

34

import com.vaadin.flow.shared.Registration;

35

36

// Spring Security integration

37

import org.springframework.security.core.Authentication;

38

import org.springframework.security.core.context.SecurityContext;

39

import org.springframework.security.core.context.SecurityContextHolder;

40

import org.springframework.security.core.userdetails.UserDetails;

41

import org.springframework.security.authentication.AnonymousAuthenticationToken;

42

import org.springframework.security.core.GrantedAuthority;

43

44

// Spring Security configuration

45

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

46

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

47

import org.springframework.security.config.http.SessionCreationPolicy;

48

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

49

import org.springframework.security.crypto.password.PasswordEncoder;

50

import org.springframework.security.web.SecurityFilterChain;

51

import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

52

53

// Method-level security

54

import org.springframework.security.access.prepost.PreAuthorize;

55

56

// Spring framework

57

import org.springframework.context.annotation.Bean;

58

import org.springframework.context.annotation.Configuration;

59

import org.springframework.beans.factory.annotation.Autowired;

60

import org.springframework.stereotype.Component;

61

import org.springframework.stereotype.Service;

62

63

// Servlet configuration

64

import com.vaadin.flow.server.VaadinServlet;

65

import com.vaadin.flow.server.VaadinServletConfiguration;

66

import javax.servlet.annotation.WebServlet;

67

import javax.servlet.ServletException;

68

69

// Standard Java types

70

import java.security.Principal;

71

import java.util.Arrays;

72

import java.util.List;

73

import java.util.Optional;

74

import java.util.Set;

75

import java.util.UUID;

76

import java.util.regex.Pattern;

77

78

// Logging

79

import org.slf4j.Logger;

80

import org.slf4j.LoggerFactory;

81

82

// Core components

83

import com.vaadin.flow.component.Component;

84

import com.vaadin.flow.component.button.Button;

85

import com.vaadin.flow.component.orderedlayout.VerticalLayout;

86

import com.vaadin.flow.component.orderedlayout.HorizontalLayout;

87

import com.vaadin.flow.component.html.H1;

88

import com.vaadin.flow.component.notification.Notification;

89

import com.vaadin.flow.component.grid.Grid;

90

91

// Route annotations

92

import com.vaadin.flow.router.Route;

93

import com.vaadin.flow.router.PageTitle;

94

```

95

96

## Authentication Annotations

97

98

### Core Security Annotations

99

100

Built-in annotations for declarative access control.

101

102

```java { .api }

103

@Target({ElementType.TYPE, ElementType.METHOD})

104

@Retention(RetentionPolicy.RUNTIME)

105

public @interface AnonymousAllowed {

106

// Allows access to anonymous (unauthenticated) users

107

}

108

109

@Target({ElementType.TYPE, ElementType.METHOD})

110

@Retention(RetentionPolicy.RUNTIME)

111

public @interface PermitAll {

112

// Allows access to all authenticated users

113

}

114

115

@Target({ElementType.TYPE, ElementType.METHOD})

116

@Retention(RetentionPolicy.RUNTIME)

117

public @interface DenyAll {

118

// Denies access to all users

119

}

120

121

@Target({ElementType.TYPE, ElementType.METHOD})

122

@Retention(RetentionPolicy.RUNTIME)

123

public @interface RolesAllowed {

124

String[] value(); // Specifies allowed roles

125

}

126

```

127

128

## Authentication Integration

129

130

### SecurityContext Access

131

132

Access current authentication information.

133

134

```java { .api }

135

// Spring Security integration

136

public class SecurityService {

137

138

public UserDetails getAuthenticatedUser() {

139

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

140

if (authentication != null && authentication.isAuthenticated()) {

141

Object principal = authentication.getPrincipal();

142

if (principal instanceof UserDetails) {

143

return (UserDetails) principal;

144

}

145

}

146

return null;

147

}

148

149

public boolean isAuthenticated() {

150

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

151

return authentication != null &&

152

authentication.isAuthenticated() &&

153

!(authentication instanceof AnonymousAuthenticationToken);

154

}

155

156

public boolean hasRole(String role) {

157

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

158

if (authentication != null) {

159

return authentication.getAuthorities().stream()

160

.anyMatch(authority -> authority.getAuthority().equals("ROLE_" + role));

161

}

162

return false;

163

}

164

165

public void logout() {

166

SecurityContextHolder.clearContext();

167

VaadinSession.getCurrent().getSession().invalidate();

168

UI.getCurrent().navigate("");

169

}

170

}

171

```

172

173

### Login Components

174

175

Built-in login form components with customization options.

176

177

```java { .api }

178

public class LoginForm extends Component {

179

public LoginForm();

180

181

// Event handling

182

public Registration addLoginListener(ComponentEventListener<LoginEvent> listener);

183

public Registration addForgotPasswordListener(ComponentEventListener<ForgotPasswordEvent> listener);

184

185

// Configuration

186

public void setError(boolean error);

187

public boolean isError();

188

public void setEnabled(boolean enabled);

189

public boolean isEnabled();

190

191

// Internationalization

192

public void setI18n(LoginI18n i18n);

193

public LoginI18n getI18n();

194

195

// Actions

196

public void setAction(String action);

197

public String getAction();

198

public void setForgotPasswordButtonVisible(boolean forgotPasswordButtonVisible);

199

public boolean isForgotPasswordButtonVisible();

200

}

201

202

public class LoginOverlay extends LoginForm {

203

public LoginOverlay();

204

205

// Overlay control

206

public void setOpened(boolean opened);

207

public boolean isOpened();

208

209

// Title and description

210

public void setTitle(String title);

211

public String getTitle();

212

public void setDescription(String description);

213

public String getDescription();

214

}

215

216

// Login events

217

public class LoginEvent extends ComponentEvent<LoginForm> {

218

public LoginEvent(LoginForm source, boolean fromClient, String username, String password);

219

220

public String getUsername();

221

public String getPassword();

222

}

223

224

public class ForgotPasswordEvent extends ComponentEvent<LoginForm> {

225

public ForgotPasswordEvent(LoginForm source, boolean fromClient, String username);

226

227

public String getUsername();

228

}

229

230

// Internationalization

231

public class LoginI18n {

232

public Header getHeader();

233

public void setHeader(Header header);

234

public Form getForm();

235

public void setForm(Form form);

236

public ErrorMessage getErrorMessage();

237

public void setErrorMessage(ErrorMessage errorMessage);

238

239

public static class Header {

240

public String getTitle();

241

public void setTitle(String title);

242

public String getDescription();

243

public void setDescription(String description);

244

}

245

246

public static class Form {

247

public String getTitle();

248

public void setTitle(String title);

249

public String getUsername();

250

public void setUsername(String username);

251

public String getPassword();

252

public void setPassword(String password);

253

public String getSubmit();

254

public void setSubmit(String submit);

255

public String getForgotPassword();

256

public void setForgotPassword(String forgotPassword);

257

}

258

259

public static class ErrorMessage {

260

public String getTitle();

261

public void setTitle(String title);

262

public String getMessage();

263

public void setMessage(String message);

264

}

265

}

266

```

267

268

## Authorization and Access Control

269

270

### Navigation Guards

271

272

Implement authorization at the navigation level.

273

274

```java { .api }

275

public interface BeforeEnterObserver {

276

void beforeEnter(BeforeEnterEvent event);

277

}

278

279

// Example navigation guard

280

@Component

281

public class AuthenticationGuard implements BeforeEnterObserver {

282

283

@Autowired

284

private SecurityService securityService;

285

286

@Override

287

public void beforeEnter(BeforeEnterEvent event) {

288

if (!securityService.isAuthenticated()) {

289

// Redirect to login if not authenticated

290

event.rerouteTo(LoginView.class);

291

}

292

}

293

}

294

295

// Role-based navigation guard

296

public class RoleBasedGuard implements BeforeEnterObserver {

297

298

private final String requiredRole;

299

300

public RoleBasedGuard(String requiredRole) {

301

this.requiredRole = requiredRole;

302

}

303

304

@Override

305

public void beforeEnter(BeforeEnterEvent event) {

306

if (!hasRequiredRole()) {

307

event.rerouteTo(AccessDeniedView.class);

308

}

309

}

310

311

private boolean hasRequiredRole() {

312

// Check if current user has required role

313

return SecurityContextHolder.getContext().getAuthentication()

314

.getAuthorities().stream()

315

.anyMatch(auth -> auth.getAuthority().equals("ROLE_" + requiredRole));

316

}

317

}

318

```

319

320

### Programmatic Security

321

322

Programmatic access control within views and components.

323

324

```java { .api }

325

public class SecurityUtils {

326

327

public static boolean isUserLoggedIn() {

328

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

329

return authentication != null &&

330

authentication.isAuthenticated() &&

331

!(authentication instanceof AnonymousAuthenticationToken);

332

}

333

334

public static boolean hasRole(String role) {

335

return SecurityContextHolder.getContext().getAuthentication()

336

.getAuthorities().stream()

337

.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ROLE_" + role));

338

}

339

340

public static boolean hasAnyRole(String... roles) {

341

return Arrays.stream(roles).anyMatch(SecurityUtils::hasRole);

342

}

343

344

public static String getCurrentUsername() {

345

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

346

if (authentication != null && authentication.isAuthenticated()) {

347

return authentication.getName();

348

}

349

return null;

350

}

351

352

public static Optional<Object> getCurrentUser() {

353

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

354

if (authentication != null && authentication.isAuthenticated()) {

355

return Optional.ofNullable(authentication.getPrincipal());

356

}

357

return Optional.empty();

358

}

359

}

360

```

361

362

## CSRF Protection

363

364

### CSRF Token Handling

365

366

Built-in CSRF protection with token management.

367

368

```java { .api }

369

public class CSRFTokenService {

370

371

// CSRF tokens are automatically handled by Vaadin

372

// Manual token access for custom scenarios

373

374

public String getCSRFToken() {

375

VaadinSession session = VaadinSession.getCurrent();

376

if (session != null) {

377

String token = (String) session.getAttribute("csrf-token");

378

if (token == null) {

379

token = generateCSRFToken();

380

session.setAttribute("csrf-token", token);

381

}

382

return token;

383

}

384

return null;

385

}

386

387

public boolean validateCSRFToken(String token) {

388

String sessionToken = getCSRFToken();

389

return sessionToken != null && sessionToken.equals(token);

390

}

391

392

private String generateCSRFToken() {

393

return UUID.randomUUID().toString();

394

}

395

}

396

```

397

398

## Session Security

399

400

### Session Management

401

402

Secure session handling and management.

403

404

```java { .api }

405

public class SessionSecurityService {

406

407

public void invalidateSession() {

408

VaadinSession vaadinSession = VaadinSession.getCurrent();

409

if (vaadinSession != null) {

410

// Clear security context

411

SecurityContextHolder.clearContext();

412

413

// Invalidate session

414

vaadinSession.close();

415

416

// Redirect to login

417

UI.getCurrent().getPage().setLocation("/login");

418

}

419

}

420

421

public void refreshSession() {

422

VaadinSession session = VaadinSession.getCurrent();

423

if (session != null) {

424

// Force session regeneration for security

425

session.lock();

426

try {

427

// Migrate session data if needed

428

Object userData = session.getAttribute("user-data");

429

session.close();

430

431

// Create new session

432

VaadinSession newSession = VaadinSession.getCurrent();

433

if (userData != null) {

434

newSession.setAttribute("user-data", userData);

435

}

436

} finally {

437

session.unlock();

438

}

439

}

440

}

441

442

public void setSessionTimeout(int timeoutInSeconds) {

443

VaadinSession session = VaadinSession.getCurrent();

444

if (session != null) {

445

session.getSession().setMaxInactiveInterval(timeoutInSeconds);

446

}

447

}

448

449

public boolean isSessionExpired() {

450

VaadinSession session = VaadinSession.getCurrent();

451

return session == null || session.isClosed();

452

}

453

}

454

```

455

456

## Content Security Policy

457

458

### CSP Configuration

459

460

Content Security Policy configuration for enhanced security.

461

462

```java { .api }

463

@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)

464

@VaadinServletConfiguration(ui = MyUI.class)

465

public class MyUIServlet extends VaadinServlet {

466

467

@Override

468

protected void servletInitialized() throws ServletException {

469

super.servletInitialized();

470

471

// Configure CSP headers

472

getService().addSessionInitListener(event -> {

473

event.getSource().addBootstrapListener(response -> {

474

response.setHeader("Content-Security-Policy",

475

"default-src 'self'; " +

476

"script-src 'self' 'unsafe-inline' 'unsafe-eval'; " +

477

"style-src 'self' 'unsafe-inline'; " +

478

"img-src 'self' data: https:; " +

479

"connect-src 'self' ws: wss:; " +

480

"font-src 'self'; " +

481

"object-src 'none'; " +

482

"media-src 'self'; " +

483

"frame-src 'none';"

484

);

485

});

486

});

487

}

488

}

489

```

490

491

## Input Validation and Sanitization

492

493

### Data Validation

494

495

Server-side validation for security and data integrity.

496

497

```java { .api }

498

public class SecurityValidator {

499

500

private static final Pattern SQL_INJECTION_PATTERN =

501

Pattern.compile("('.+--)|(--.+)|('.+#)|(#.+)|(\\b(select|insert|update|delete|drop|create|alter|exec|execute|union|script)\\b)",

502

Pattern.CASE_INSENSITIVE);

503

504

private static final Pattern XSS_PATTERN =

505

Pattern.compile("<\\s*script\\s*.*?>|<\\s*\\/\\s*script\\s*>|javascript:|vbscript:|onload=|onerror=|onmouseover=",

506

Pattern.CASE_INSENSITIVE);

507

508

public static boolean containsSQLInjection(String input) {

509

if (input == null) return false;

510

return SQL_INJECTION_PATTERN.matcher(input).find();

511

}

512

513

public static boolean containsXSS(String input) {

514

if (input == null) return false;

515

return XSS_PATTERN.matcher(input).find();

516

}

517

518

public static String sanitizeInput(String input) {

519

if (input == null) return null;

520

521

// Remove potentially dangerous characters

522

String sanitized = input.replaceAll("[<>\"'%;()&+]", "");

523

524

// Limit length

525

if (sanitized.length() > 1000) {

526

sanitized = sanitized.substring(0, 1000);

527

}

528

529

return sanitized.trim();

530

}

531

532

public static boolean isValidEmail(String email) {

533

return email != null &&

534

email.matches("^[A-Za-z0-9+_.-]+@([A-Za-z0-9.-]+\\.[A-Za-z]{2,})$") &&

535

email.length() <= 254;

536

}

537

538

public static boolean isValidUsername(String username) {

539

return username != null &&

540

username.matches("^[a-zA-Z0-9_.-]{3,50}$");

541

}

542

}

543

```

544

545

## Security Event Handling

546

547

### Security Events

548

549

Handle security-related events and logging.

550

551

```java { .api }

552

public class SecurityEventService {

553

554

private static final Logger logger = LoggerFactory.getLogger(SecurityEventService.class);

555

556

public void logSuccessfulLogin(String username, String ipAddress) {

557

logger.info("Successful login - User: {}, IP: {}", username, ipAddress);

558

// Store in audit log

559

}

560

561

public void logFailedLogin(String username, String ipAddress) {

562

logger.warn("Failed login attempt - User: {}, IP: {}", username, ipAddress);

563

// Implement brute force protection

564

}

565

566

public void logLogout(String username) {

567

logger.info("User logout - User: {}", username);

568

}

569

570

public void logSecurityViolation(String username, String violation, String details) {

571

logger.error("Security violation - User: {}, Violation: {}, Details: {}",

572

username, violation, details);

573

// Alert security team

574

}

575

576

public void logAccessDenied(String username, String resource) {

577

logger.warn("Access denied - User: {}, Resource: {}", username, resource);

578

}

579

}

580

```

581

582

## Secure Configuration

583

584

### Security Configuration

585

586

Best practices for secure Vaadin application configuration.

587

588

```java { .api }

589

@Configuration

590

@EnableWebSecurity

591

public class SecurityConfiguration {

592

593

@Bean

594

public PasswordEncoder passwordEncoder() {

595

return new BCryptPasswordEncoder(12);

596

}

597

598

@Bean

599

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

600

return http

601

.authorizeHttpRequests(auth -> auth

602

.requestMatchers("/login", "/register", "/public/**").permitAll()

603

.requestMatchers("/admin/**").hasRole("ADMIN")

604

.anyRequest().authenticated()

605

)

606

.formLogin(form -> form

607

.loginPage("/login")

608

.defaultSuccessUrl("/dashboard")

609

.failureUrl("/login?error=true")

610

.permitAll()

611

)

612

.logout(logout -> logout

613

.logoutUrl("/logout")

614

.logoutSuccessUrl("/login")

615

.invalidateHttpSession(true)

616

.deleteCookies("JSESSIONID")

617

.permitAll()

618

)

619

.sessionManagement(session -> session

620

.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)

621

.maximumSessions(1)

622

.maxSessionsPreventsLogin(false)

623

)

624

.csrf(csrf -> csrf

625

.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

626

)

627

.headers(headers -> headers

628

.frameOptions().deny()

629

.contentTypeOptions().and()

630

.httpStrictTransportSecurity(hsts -> hsts

631

.maxAgeInSeconds(31536000)

632

.includeSubdomains(true)

633

)

634

)

635

.build();

636

}

637

}

638

```

639

640

## Usage Examples

641

642

### Secured View Implementation

643

644

```java

645

@Route("admin/users")

646

@PageTitle("User Management")

647

@RolesAllowed("ADMIN")

648

public class UserManagementView extends VerticalLayout implements BeforeEnterObserver {

649

650

@Autowired

651

private SecurityService securityService;

652

653

@Autowired

654

private UserService userService;

655

656

private Grid<User> userGrid;

657

658

public UserManagementView() {

659

setupUI();

660

}

661

662

@Override

663

public void beforeEnter(BeforeEnterEvent event) {

664

// Additional security check

665

if (!securityService.hasRole("ADMIN")) {

666

event.rerouteTo(AccessDeniedView.class);

667

return;

668

}

669

670

// Log access

671

String currentUser = securityService.getAuthenticatedUser().getUsername();

672

logger.info("Admin access - User: {}, View: UserManagement", currentUser);

673

}

674

675

private void setupUI() {

676

H1 title = new H1("User Management");

677

678

userGrid = new Grid<>(User.class);

679

configureGrid();

680

681

Button addUserButton = new Button("Add User");

682

addUserButton.addClickListener(e -> addUser());

683

684

add(title, addUserButton, userGrid);

685

}

686

687

private void configureGrid() {

688

userGrid.setColumns("username", "email", "role", "lastLogin");

689

userGrid.addComponentColumn(user -> createActionButtons(user))

690

.setHeader("Actions");

691

692

userGrid.setItems(userService.findAll());

693

}

694

695

private Component createActionButtons(User user) {

696

Button editButton = new Button("Edit");

697

editButton.addClickListener(e -> editUser(user));

698

699

Button deleteButton = new Button("Delete");

700

deleteButton.addClickListener(e -> confirmDeleteUser(user));

701

deleteButton.getStyle().set("color", "var(--lumo-error-color)");

702

703

return new HorizontalLayout(editButton, deleteButton);

704

}

705

}

706

```

707

708

### Login View with Security

709

710

```java

711

@Route("login")

712

@PageTitle("Login")

713

@AnonymousAllowed

714

public class LoginView extends VerticalLayout {

715

716

@Autowired

717

private SecurityEventService securityEventService;

718

719

private LoginForm loginForm;

720

721

public LoginView() {

722

setupUI();

723

}

724

725

private void setupUI() {

726

setSizeFull();

727

setJustifyContentMode(JustifyContentMode.CENTER);

728

setAlignItems(Alignment.CENTER);

729

730

loginForm = new LoginForm();

731

loginForm.setAction("login");

732

loginForm.addLoginListener(this::handleLogin);

733

734

// Customize appearance

735

LoginI18n i18n = LoginI18n.createDefault();

736

i18n.getForm().setTitle("Secure Application");

737

i18n.getForm().setUsername("Username");

738

i18n.getForm().setPassword("Password");

739

i18n.getForm().setSubmit("Sign In");

740

loginForm.setI18n(i18n);

741

742

add(loginForm);

743

}

744

745

private void handleLogin(LoginEvent event) {

746

String username = event.getUsername();

747

String ipAddress = getClientIP();

748

749

try {

750

// Validate input

751

if (!SecurityValidator.isValidUsername(username)) {

752

loginForm.setError(true);

753

securityEventService.logSecurityViolation(username, "Invalid username format", ipAddress);

754

return;

755

}

756

757

// Additional security checks can be added here

758

securityEventService.logSuccessfulLogin(username, ipAddress);

759

760

} catch (Exception e) {

761

loginForm.setError(true);

762

securityEventService.logFailedLogin(username, ipAddress);

763

}

764

}

765

766

private String getClientIP() {

767

VaadinRequest request = VaadinService.getCurrentRequest();

768

return request != null ? request.getRemoteAddr() : "unknown";

769

}

770

}

771

```

772

773

### Secure Data Access

774

775

```java

776

@Service

777

public class SecureUserService {

778

779

@Autowired

780

private UserRepository userRepository;

781

782

@Autowired

783

private SecurityEventService securityEventService;

784

785

@PreAuthorize("hasRole('ADMIN') or authentication.name == #username")

786

public User getUserByUsername(String username) {

787

// Validate input

788

if (!SecurityValidator.isValidUsername(username)) {

789

throw new IllegalArgumentException("Invalid username format");

790

}

791

792

return userRepository.findByUsername(username);

793

}

794

795

@PreAuthorize("hasRole('ADMIN')")

796

public List<User> getAllUsers() {

797

String currentUser = SecurityContextHolder.getContext()

798

.getAuthentication().getName();

799

800

securityEventService.logSecurityViolation(currentUser,

801

"Admin access", "Retrieved all users");

802

803

return userRepository.findAll();

804

}

805

806

@PreAuthorize("hasRole('ADMIN') or authentication.name == #user.username")

807

public User saveUser(User user) {

808

// Sanitize input

809

user.setEmail(SecurityValidator.sanitizeInput(user.getEmail()));

810

user.setUsername(SecurityValidator.sanitizeInput(user.getUsername()));

811

812

// Validate data

813

if (!SecurityValidator.isValidEmail(user.getEmail())) {

814

throw new IllegalArgumentException("Invalid email format");

815

}

816

817

return userRepository.save(user);

818

}

819

}

820

```

821

822

The security system provides comprehensive protection while maintaining ease of development through declarative annotations and programmatic APIs.