多Tomcat服务器Vaadin应用跨域基础认证及Auth Header传递方案咨询
跨多Tomcat/Vaadin应用的统一基础认证方案
针对你提到的跨多台Tomcat服务器上的Vaadin应用实现统一基础认证、登录后自动携带Auth Header的需求,这里有几个可行的方案,帮你解决之前JS方案遇到的跨域问题:
方案一:Tomcat容器级单点登录(SSO)
这是最贴合你现有Tomcat环境的方案,利用Tomcat自带的SSO功能实现跨应用认证共享,不需要大量修改Vaadin代码:
- 配置步骤:
- 在所有Tomcat的
server.xml中添加SSO Valve,确保所有Tomcat的域配置一致(比如主域名都是*.yourdomain.com):<Valve className="org.apache.catalina.authenticator.SingleSignOn" /> - 统一所有Tomcat的Realm配置,比如使用同一个JDBCRealm或LDAPRealm,让所有服务器共享用户认证数据:
<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://your-db-host/auth_db?useSSL=true" connectionName="db-user" connectionPassword="db-pass" userTable="users" userNameCol="username" userCredCol="password" userRoleTable="user_roles" roleNameCol="role"/> - 每个Vaadin应用的
web.xml中启用基础认证:<login-config> <auth-method>BASIC</auth-method> <realm-name>Your Auth Realm</realm-name> </login-config>
- 在所有Tomcat的
- 效果:用户在任意一个应用登录后,Tomcat会在主域名下生成共享的SSO Cookie,访问其他同域下的Vaadin应用时,Tomcat会自动识别认证状态,无需重复登录,且会自动处理Auth Header的传递。
方案二:共享认证Cookie+Vaadin全局拦截
如果不想依赖Tomcat的SSO,也可以通过共享Cookie结合Vaadin的全局拦截器来实现自动携带Auth Header:
- 解决跨域问题:将所有应用部署在同一个主域的子域名下(比如
app1.yourdomain.com、app2.yourdomain.com),然后在登录成功后,将基础认证的Base64字符串存储在父域Cookie中:// 登录成功后设置跨子域的Cookie(假设主域是yourdomain.com) document.cookie = "authToken=" + btoa(username + ":" + password) + "; domain=.yourdomain.com; path=/; secure; HttpOnly"; - Vaadin应用自动注入Header:在每个Vaadin应用中添加
VaadinServiceInitListener,拦截所有请求并自动添加Auth Header:@WebListener public class AuthHeaderInitializer implements VaadinServiceInitListener { @Override public void serviceInit(ServiceInitEvent event) { event.getSource().addRequestHandler((session, request, response) -> { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("authToken".equals(cookie.getName())) { request.addHeader("Authorization", "Basic " + cookie.getValue()); break; } } } return false; }); } } - 注意:必须确保所有应用的Cookie域配置正确,且如果使用HTTPS,要开启
Secure属性保障安全。
方案三:反向代理统一处理认证
如果不想修改Tomcat或Vaadin代码,可以用Nginx/Apache作为反向代理,在代理层实现统一的基础认证:
- Nginx配置示例:
http { # 共享认证缓存 proxy_cache_path /var/cache/nginx/auth_cache levels=1:2 keys_zone=auth_cache:10m max_size=10g inactive=24h use_temp_path=off; server { listen 443 ssl; server_name *.yourdomain.com; # 统一基础认证 auth_basic "Your Protected Realm"; auth_basic_user_file /etc/nginx/.htpasswd; # 缓存认证状态,避免重复验证 proxy_cache auth_cache; proxy_cache_key "$remote_user$request_uri"; proxy_cache_valid 200 1h; # 转发请求到对应Tomcat location /app1/ { proxy_pass http://tomcat1:8080/app1/; proxy_set_header Authorization $http_authorization; } location /app2/ { proxy_pass http://tomcat2:8080/app2/; proxy_set_header Authorization $http_authorization; } } } - 效果:用户在第一次访问任意应用时输入用户名密码,Nginx会验证并缓存认证状态,后续访问其他应用时,Nginx自动将Auth Header转发到后端Tomcat,实现无感知的跨应用认证。
为什么之前的JS方案失败?
你用XMLHttpRequest遇到的问题,本质是浏览器同源策略限制:跨域请求默认无法操作其他域名的Cookie或自定义Header,即使配置了CORS,也需要服务器端配合开启Access-Control-Allow-Credentials等头,且操作Header的权限有限。相比之下,上面的容器级或代理级方案绕过了前端跨域限制,实现更可靠。
内容的提问来源于stack exchange,提问作者MultiShinigami30
相关产品推荐
相关产品推荐

