security
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSecurity with Spring Security in Vaadin 25
Vaadin 25 中使用 Spring Security 实现安全防护
Use the Vaadin MCP tools (, , ) to look up the latest documentation whenever uncertain about a specific API detail. Always set to and to .
search_vaadin_docsget_component_java_apiget_component_stylingvaadin_version"25"ui_language"java"当对特定API细节不确定时,使用Vaadin MCP工具(、、)查阅最新文档。请始终将设置为,设置为。
search_vaadin_docsget_component_java_apiget_component_stylingvaadin_version"25"ui_language"java"When to Use This Skill vs. Others
何时使用此技能而非其他技能
This skill covers: Spring Security configuration with , login views with , view access control annotations (, , , ), , logout handling, and OAuth2/OpenID Connect integration with providers like Google, Keycloak, GitHub, and Okta.
VaadinSecurityConfigurerLoginForm@AnonymousAllowed@PermitAll@RolesAllowed@DenyAllAuthenticationContextUse instead when the question is about , , , , or URL parameters. This skill covers how to secure views, not how to create or navigate between them.
views-and-navigation@Route@LayoutAppLayoutSideNavUse instead when securing React/Hilla views with and . This skill covers Java/Flow view security, though the annotation-based approach also applies to endpoints.
client-side-viewsViewConfig.loginRequiredViewConfig.rolesAllowed@BrowserCallable此技能涵盖: 使用配置Spring Security、使用实现登录视图、视图访问控制注解(、、、)、、登出处理,以及与Google、Keycloak、GitHub、Okta等提供商集成OAuth2/OpenID Connect。
VaadinSecurityConfigurerLoginForm@AnonymousAllowed@PermitAll@RolesAllowed@DenyAllAuthenticationContext当问题涉及、、、或URL参数时,请改用技能。此技能仅涵盖如何保护视图,而非如何创建或导航视图。
@Route@LayoutAppLayoutSideNavviews-and-navigation当使用和保护React/Hilla视图时,请改用技能。此技能涵盖Java/Flow视图的安全防护,不过基于注解的方法也适用于端点。
ViewConfig.loginRequiredViewConfig.rolesAllowedclient-side-views@BrowserCallableSetting Up Spring Security
配置Spring Security
Add the Spring Security starter dependency:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>Create a security configuration class that uses :
VaadinSecurityConfigurerjava
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
configurer.loginView(LoginView.class);
});
return http.build();
}
@Bean
public UserDetailsManager userDetailsManager() {
// WARNING: In-memory users for development only.
// Use JDBC, LDAP, or OAuth2 in production.
var user = User.withUsername("user")
.password("{noop}user")
.roles("USER")
.build();
var admin = User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}VaadinSecurityConfigurer.vaadin()- CSRF — enabled with exemptions for Vaadin internal requests
- Logout — configured with Vaadin-aware logout handlers
- Request cache — Vaadin-specific request cache for redirect after login
- Exception handling — proper error responses for Vaadin requests
- Authorized requests — permits Vaadin framework requests (client engine, push, etc.)
- Navigation access control — enforces view access annotations
添加Spring Security starter依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>创建使用的安全配置类:
VaadinSecurityConfigurerjava
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
configurer.loginView(LoginView.class);
});
return http.build();
}
@Bean
public UserDetailsManager userDetailsManager() {
// 警告:仅在开发环境使用内存用户。
// 生产环境请使用JDBC、LDAP或OAuth2。
var user = User.withUsername("user")
.password("{noop}user")
.roles("USER")
.build();
var admin = User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}VaadinSecurityConfigurer.vaadin()- CSRF —— 启用并豁免Vaadin内部请求
- 登出 —— 配置Vaadin感知的登出处理器
- 请求缓存 —— 用于登录后重定向的Vaadin特定请求缓存
- 异常处理 —— 为Vaadin请求返回正确的错误响应
- 授权请求 —— 允许Vaadin框架请求(客户端引擎、推送等)
- 导航访问控制 —— 强制执行视图访问注解
Login View
登录视图
Use the built-in component to create a login page. It provides a form with username and password fields, is compatible with password managers, and handles CSRF tokens automatically.
LoginFormjava
@Route(value = "login", autoLayout = false)
@PageTitle("Login")
@AnonymousAllowed
public class LoginView extends Main implements BeforeEnterObserver {
private final LoginForm login;
public LoginView() {
login = new LoginForm();
login.setAction("login");
addClassNames(LumoUtility.Display.FLEX,
LumoUtility.JustifyContent.CENTER,
LumoUtility.AlignItems.CENTER);
setSizeFull();
add(login);
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
if (event.getLocation()
.getQueryParameters()
.getParameters()
.containsKey("error")) {
login.setError(true);
}
}
}Key points:
- — prevents the login view from rendering inside the application's main layout (e.g.,
autoLayout = falsewith navigation menu)AppLayout - — required so unauthenticated users can access the page
@AnonymousAllowed - — makes the form POST to Spring Security's
login.setAction("login")endpoint/login - — checks for the
BeforeEnterObserverquery parameter that Spring Security adds after a failed login attempt?error - Register in SecurityConfig — tells VaadinSecurityConfigurer which view is the login page
configurer.loginView(LoginView.class)
使用内置的组件创建登录页面。它提供带有用户名和密码字段的表单,兼容密码管理器,并自动处理CSRF令牌。
LoginFormjava
@Route(value = "login", autoLayout = false)
@PageTitle("Login")
@AnonymousAllowed
public class LoginView extends Main implements BeforeEnterObserver {
private final LoginForm login;
public LoginView() {
login = new LoginForm();
login.setAction("login");
addClassNames(LumoUtility.Display.FLEX,
LumoUtility.JustifyContent.CENTER,
LumoUtility.AlignItems.CENTER);
setSizeFull();
add(login);
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
if (event.getLocation()
.getQueryParameters()
.getParameters()
.containsKey("error")) {
login.setError(true);
}
}
}关键点:
- —— 防止登录视图渲染在应用的主布局内(例如带有导航菜单的
autoLayout = false)AppLayout - —— 必须添加,以便未认证用户可以访问该页面
@AnonymousAllowed - —— 使表单POST到Spring Security的
login.setAction("login")端点/login - —— 检查Spring Security在登录失败后添加的
BeforeEnterObserver查询参数?error - 在SecurityConfig中注册 —— 告诉VaadinSecurityConfigurer哪个视图是登录页面
configurer.loginView(LoginView.class)
View Access Control
视图访问控制
Control who can access each view using Jakarta and Vaadin security annotations on the view class:
| Annotation | Access Level | Typical Use |
|---|---|---|
| Anyone (no login required) | Login view, public landing page |
| Any authenticated user | Dashboard, user profile |
| Users with specified role(s) | Admin panel, user management |
| Nobody | Default when no annotation is present |
Note on: Vaadin's use of@PermitAlldiffers from the Jakarta Security standard. In standard Jakarta Security,@PermitAllmeans "anyone, including unauthenticated users" — similar to Vaadin's@PermitAll. In Vaadin,@AnonymousAllowedmeans "any authenticated user." Developers familiar with standard Jakarta security may be confused when access is denied to unauthenticated users on a view they explicitly "permitted all" — use@PermitAllfor truly public views.@AnonymousAllowed
java
@Route("public")
@AnonymousAllowed
public class PublicView extends VerticalLayout { }
@Route("dashboard")
@PermitAll
public class DashboardView extends VerticalLayout { }
@Route("admin")
@RolesAllowed("ADMIN")
public class AdminView extends VerticalLayout { }在视图类上使用Jakarta和Vaadin安全注解控制谁可以访问每个视图:
| 注解 | 访问级别 | 典型用途 |
|---|---|---|
| 任何人(无需登录) | 登录视图、公共着陆页 |
| 任何已认证用户 | 仪表盘、用户资料页 |
| 拥有指定角色的用户 | 管理面板、用户管理页 |
| 无人可访问 | 未添加注解时的默认设置 |
关于的注意事项: Vaadin对@PermitAll的使用与Jakarta Security标准不同。在标准Jakarta Security中,@PermitAll表示“任何人,包括未认证用户”——与Vaadin的@PermitAll类似。而在Vaadin中,@AnonymousAllowed表示“任何已认证用户”。熟悉标准Jakarta Security的开发者可能会困惑,为什么他们明确“允许所有”的视图会拒绝未认证用户访问——对于真正的公共视图,请使用@PermitAll。@AnonymousAllowed
java
@Route("public")
@AnonymousAllowed
public class PublicView extends VerticalLayout { }
@Route("dashboard")
@PermitAll
public class DashboardView extends VerticalLayout { }
@Route("admin")
@RolesAllowed("ADMIN")
public class AdminView extends VerticalLayout { }Annotation Resolution Rules
注解解析规则
- No annotation on a view — applies (access denied by default)
@DenyAll - Superclass annotations — inherited from the closest annotated parent class
- Child class annotated — overrides parent class annotations
- Interfaces — annotations on interfaces are not checked
- Layouts are checked independently — both the layout and the view must grant access. A view with inside a layout with no annotation (default
@PermitAll) is inaccessible@DenyAll - Override priority when multiple annotations exist — >
@DenyAll>@AnonymousAllowed>@RolesAllowed@PermitAll
- 视图未添加注解 —— 应用(默认拒绝访问)
@DenyAll - 父类注解 —— 继承自最近的已注解父类
- 子类添加注解 —— 覆盖父类注解
- 接口 —— 不检查接口上的注解
- 布局独立检查 —— 布局和视图都必须授予访问权限。带有的视图若位于未添加注解的布局(默认
@PermitAll)内,则无法访问@DenyAll - 多个注解存在时的优先级 —— >
@DenyAll>@AnonymousAllowed>@RolesAllowed@PermitAll
Role Constants
角色常量
Define role names as constants to avoid typos in annotations:
@RolesAllowedjava
public final class Roles {
public static final String ADMIN = "ADMIN";
public static final String USER = "USER";
private Roles() {
}
}
// Usage:
@RolesAllowed(Roles.ADMIN)
public class AdminView extends VerticalLayout { }将角色名称定义为常量,避免在注解中出现拼写错误:
@RolesAllowedjava
public final class Roles {
public static final String ADMIN = "ADMIN";
public static final String USER = "USER";
private Roles() {
}
}
// 使用方式:
@RolesAllowed(Roles.ADMIN)
public class AdminView extends VerticalLayout { }Programmatic Access Checks
程序化访问检查
Inject to check roles or get user information within a view:
AuthenticationContextjava
@Route("settings")
@PermitAll
public class SettingsView extends VerticalLayout {
public SettingsView(AuthenticationContext authContext) {
authContext.getAuthenticatedUser(UserDetails.class)
.ifPresent(user -> add(new H2("Welcome " + user.getUsername())));
if (authContext.hasRole(Roles.ADMIN)) {
add(new Button("Admin Settings", event -> {
// show admin-only settings
}));
}
}
}注入以在视图内检查角色或获取用户信息:
AuthenticationContextjava
@Route("settings")
@PermitAll
public class SettingsView extends VerticalLayout {
public SettingsView(AuthenticationContext authContext) {
authContext.getAuthenticatedUser(UserDetails.class)
.ifPresent(user -> add(new H2("Welcome " + user.getUsername())));
if (authContext.hasRole(Roles.ADMIN)) {
add(new Button("Admin Settings", event -> {
// 显示仅管理员可见的设置
}));
}
}
}Logout
登出
AuthenticationContext (Recommended)
AuthenticationContext(推荐方式)
The simplest and most reliable way to log out. handles session invalidation and redirect automatically. Add a logout button to your :
AuthenticationContextMainLayoutjava
public class MainLayout extends AppLayout {
private final transient AuthenticationContext authContext;
public MainLayout(AuthenticationContext authContext) {
this.authContext = authContext;
var title = new H1("My App");
title.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE);
var logout = new Button("Logout", event -> authContext.logout());
var header = new HorizontalLayout(title, logout);
header.setWidthFull();
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
header.setAlignItems(FlexComponent.Alignment.CENTER);
header.addClassNames(LumoUtility.Padding.Horizontal.MEDIUM);
addToNavbar(header);
}
}AuthenticationContexttransientSerializableBy default, logout redirects to . To customize the post-logout redirect, specify a second parameter when registering the login view:
/java
configurer.loginView(LoginView.class, "/goodbye");最简单且最可靠的登出方式。会自动处理会话失效和重定向。在中添加登出按钮:
AuthenticationContextMainLayoutjava
public class MainLayout extends AppLayout {
private final transient AuthenticationContext authContext;
public MainLayout(AuthenticationContext authContext) {
this.authContext = authContext;
var title = new H1("My App");
title.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE);
var logout = new Button("Logout", event -> authContext.logout());
var header = new HorizontalLayout(title, logout);
header.setWidthFull();
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
header.setAlignItems(FlexComponent.Alignment.CENTER);
header.addClassNames(LumoUtility.Padding.Horizontal.MEDIUM);
addToNavbar(header);
}
}AuthenticationContexttransientSerializable默认情况下,登出后会重定向到。要自定义登出后的重定向地址,请在注册登录视图时指定第二个参数:
/java
configurer.loginView(LoginView.class, "/goodbye");SecurityContextLogoutHandler (Alternative)
SecurityContextLogoutHandler(替代方式)
When is not available, use directly. The redirect must happen before the handler invalidates the session:
AuthenticationContextSecurityContextLogoutHandlerjava
public void logout() {
UI.getCurrent().getPage().setLocation("/");
var logoutHandler = new SecurityContextLogoutHandler();
logoutHandler.logout(
VaadinServletRequest.getCurrent().getHttpServletRequest(),
null, null);
}当无法使用时,可直接使用。必须在处理器失效会话前执行重定向:
AuthenticationContextSecurityContextLogoutHandlerjava
public void logout() {
UI.getCurrent().getPage().setLocation("/");
var logoutHandler = new SecurityContextLogoutHandler();
logoutHandler.logout(
VaadinServletRequest.getCurrent().getHttpServletRequest(),
null, null);
}OAuth2 / OpenID Connect
OAuth2 / OpenID Connect
To authenticate users via an external identity provider (Google, GitHub, Keycloak, Okta, Azure AD), use Spring Security's OAuth2 client support.
要通过外部身份提供商(Google、GitHub、Keycloak、Okta、Azure AD)认证用户,请使用Spring Security的OAuth2客户端支持。
Dependencies
依赖
Add the OAuth2 client starter alongside Spring Security:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>在Spring Security之外添加OAuth2 client starter依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>Google (Common Provider)
Google(常见提供商)
Google is a Spring Security "common provider", so minimal configuration is needed. Only the client ID and secret are required:
properties
spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
spring.security.oauth2.client.registration.google.scope=openid,profile,emailGoogle是Spring Security的“常见提供商”,因此只需最少配置。仅需客户端ID和密钥:
properties
spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
spring.security.oauth2.client.registration.google.scope=openid,profile,emailKeycloak (Custom Provider)
Keycloak(自定义提供商)
Providers that are not built into Spring Security require full configuration including the issuer URI:
properties
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.client-id=my-client-id
spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET}
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid,profile
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://keycloak.local:8180/realms/my-app未内置到Spring Security的提供商需要完整配置,包括颁发者URI:
properties
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.client-id=my-client-id
spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET}
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid,profile
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://keycloak.local:8180/realms/my-appSecurityConfig for OAuth2
OAuth2的SecurityConfig配置
Replace with , pointing to the provider's authorization URI:
loginView()oauth2LoginPage()java
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
configurer.oauth2LoginPage(
"/oauth2/authorization/google",
"{baseUrl}");
});
return http.build();
}
}The template variable resolves to the application's base URL and is used as the post-logout redirect URI. Other supported variables: , , , .
{baseUrl}{baseScheme}{baseHost}{basePort}{basePath}When using OAuth2, no class is needed — the identity provider handles the login UI. Users are redirected to the provider's login page and back to the application after authentication.
LoginView将替换为,指向提供商的授权URI:
loginView()oauth2LoginPage()java
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
configurer.oauth2LoginPage(
"/oauth2/authorization/google",
"{baseUrl}");
});
return http.build();
}
}{baseUrl}{baseScheme}{baseHost}{basePort}{basePath}使用OAuth2时,无需创建类——身份提供商会处理登录UI。用户会被重定向到提供商的登录页面,认证完成后返回应用。
LoginViewOAuth2 Logout
OAuth2登出
For OAuth2 applications, use the same way as with form login. The handles the OAuth2-specific logout flow.
AuthenticationContext.logout()VaadinSecurityConfigurer对于OAuth2应用,使用的方式与表单登录相同。会处理OAuth2特定的登出流程。
AuthenticationContext.logout()VaadinSecurityConfigurerOther Providers
其他提供商
The same pattern works for GitHub, Okta, and Azure AD. The only differences are:
- — the registration and provider keys change per provider
application.properties - URL — use
oauth2LoginPage()where/oauth2/authorization/{registrationId}matches the key in{registrationId}application.properties - Common providers (Google, GitHub, Facebook, Okta) need only ,
client-id, andclient-secretscope - Custom providers (Keycloak, Azure AD) also need and
issuer-uriauthorization-grant-type
相同模式适用于GitHub、Okta和Azure AD。唯一的区别在于:
- —— 注册和提供商密钥因提供商而异
application.properties - URL —— 使用
oauth2LoginPage(),其中/oauth2/authorization/{registrationId}与{registrationId}中的密钥匹配application.properties - 常见提供商(Google、GitHub、Facebook、Okta)仅需、
client-id和client-secretscope - 自定义提供商(Keycloak、Azure AD)还需要和
issuer-uriauthorization-grant-type
Best Practices
最佳实践
- Never hard-code credentials — use environment variables or a secrets manager. The with
UserDetailsManagerpasswords is for development only.{noop} - Annotate every view and layout — views without an access annotation default to . Layouts are checked independently; both must grant access.
@DenyAll - Use for logout and user info — it integrates with Spring Security and handles session cleanup correctly. Declare the field
AuthenticationContext.transient - Use on the login view — the login view should not render inside the application's main layout.
autoLayout = false - Prefer over manual Spring Security config — it handles CSRF, logout, request caching, and exception handling for Vaadin automatically.
VaadinSecurityConfigurer - Externalize OAuth2 credentials — use with environment variable references (
application.properties) or Spring profiles.${GOOGLE_CLIENT_SECRET} - Define role constants — create a class with
Rolesfields to avoid typos inpublic static final Stringannotations.@RolesAllowed - Leverage Vaadin's server-side security model — UI state lives on the server, so attackers cannot tamper with it from the browser. Combined with annotation-based access control, this provides defense in depth.
- 切勿硬编码凭证 —— 使用环境变量或密钥管理器。带有密码的
{noop}仅用于开发环境。UserDetailsManager - 为每个视图和布局添加注解 —— 未添加访问注解的视图默认使用。布局会独立检查;两者都必须授予访问权限。
@DenyAll - 使用处理登出和用户信息 —— 它与Spring Security集成,能正确处理会话清理。请将字段声明为
AuthenticationContext。transient - 在登录视图上使用—— 登录视图不应渲染在应用的主布局内。
autoLayout = false - 优先使用而非手动配置Spring Security —— 它会自动处理Vaadin的CSRF、登出、请求缓存和异常处理。
VaadinSecurityConfigurer - 外部化OAuth2凭证 —— 使用带有环境变量引用()的
${GOOGLE_CLIENT_SECRET}或Spring配置文件。application.properties - 定义角色常量 —— 创建类,包含
Roles字段,避免在public static final String注解中出现拼写错误。@RolesAllowed - 利用Vaadin的服务器端安全模型 —— UI状态存储在服务器端,攻击者无法从浏览器篡改。结合基于注解的访问控制,可提供深度防御。
Anti-Patterns
反模式
- Forgetting on the login view — the login form renders inside the app shell with the navigation menu, which is confusing and may cause access control issues.
autoLayout = false - Forgetting to annotate the layout — a view marked inside a layout with no annotation (default
@PermitAll) is inaccessible. Both must independently grant access.@DenyAll - Using or
@Securedon views — these Spring Security annotations are not supported on Vaadin views. Use@PreAuthorize,@AnonymousAllowed,@PermitAll, or@RolesAllowed.@DenyAll - Hard-coding passwords in — in-memory
SecurityConfigpasswords are for prototyping only. Production applications must use JDBC, LDAP, or OAuth2 authentication.{noop} - Calling without redirecting first — the logout handler invalidates the session, so
SecurityContextLogoutHandlermust happen before the handler call. PreferUI.getCurrent().getPage().setLocation()which handles this correctly.AuthenticationContext.logout() - Using URL-pattern security for view access control — Vaadin uses a single servlet endpoint for all views; the browser URL is updated client-side but all requests go to the same server endpoint. This means URL-pattern rules in (e.g.,
HttpSecurity) do not control access to Vaadin views. Use annotation-based access control (.requestMatchers("/admin/**").hasRole("ADMIN"),@RolesAllowed, etc.) exclusively for view security. URL-pattern rules are still appropriate for non-Vaadin endpoints such as REST APIs.@PermitAll
- 忘记在登录视图上设置—— 登录表单会渲染在应用外壳和导航菜单内,这会造成混淆并可能导致访问控制问题。
autoLayout = false - 忘记为布局添加注解 —— 带有的视图若位于未添加注解的布局(默认
@PermitAll)内,则无法访问。两者都必须独立授予访问权限。@DenyAll - 在视图上使用或
@Secured—— 这些Spring Security注解不支持Vaadin视图。请使用@PreAuthorize、@AnonymousAllowed、@PermitAll或@RolesAllowed。@DenyAll - 在中硬编码密码 —— 内存中的
SecurityConfig密码仅用于原型开发。生产应用必须使用JDBC、LDAP或OAuth2认证。{noop} - 未先重定向就调用—— 登出处理器会失效会话,因此
SecurityContextLogoutHandler必须在调用处理器前执行。优先使用UI.getCurrent().getPage().setLocation(),它能正确处理此流程。AuthenticationContext.logout() - 使用URL模式安全控制视图访问 —— Vaadin使用单个Servlet端点处理所有视图;浏览器URL会在客户端更新,但所有请求都发送到同一个服务器端点。这意味着中的URL模式规则(例如
HttpSecurity)无法控制Vaadin视图的访问。请仅使用基于注解的访问控制(.requestMatchers("/admin/**").hasRole("ADMIN")、@RolesAllowed等)进行视图安全防护。URL模式规则仍适用于非Vaadin端点,如REST API。@PermitAll
Detailed Reference
详细参考
For a quick-reference cheatsheet of security annotations, OAuth2 provider configurations, login view checklist, and SecurityConfig templates, see .
references/security-patterns.md如需安全注解、OAuth2提供商配置、登录视图检查清单和SecurityConfig模板的速查表,请参阅。
references/security-patterns.md